# HG changeset patch # User jwe # Date 1109361328 0 # Node ID 57077d0ddc8ed8895142555b01a69b7f322b52ca # Parent 9f3299378193a965cf87ff26e4d23fc445b4a791 [project @ 2005-02-25 19:55:24 by jwe] diff --git a/Makeconf.in b/Makeconf.in --- a/Makeconf.in +++ b/Makeconf.in @@ -101,13 +101,21 @@ TMP_IF_1 = -I. -I$(srcdir) endif ifeq ($(TOPDIR),$(top_srcdir)) - TMP_IF_2 = -I$(TOPDIR) -I$(TOPDIR)/liboctave -I$(TOPDIR)/src \ - -I$(TOPDIR)/libcruft/misc + TMP_IF_2 = \ + -I$(TOPDIR) \ + -I$(TOPDIR)/liboctave \ + -I$(TOPDIR)/src \ + -I$(TOPDIR)/libcruft/misc else - TMP_IF_2 = -I$(TOPDIR) -I$(TOPDIR)/liboctave -I$(TOPDIR)/src \ - -I$(TOPDIR)/libcruft/misc -I$(top_srcdir) \ - -I$(top_srcdir)/liboctave -I$(top_srcdir)/src \ - -I$(top_srcdir)/libcruft/misc + TMP_IF_2 = \ + -I$(TOPDIR) \ + -I$(TOPDIR)/liboctave \ + -I$(TOPDIR)/src \ + -I$(TOPDIR)/libcruft/misc \ + -I$(top_srcdir) \ + -I$(top_srcdir)/liboctave \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/libcruft/misc endif INCFLAGS = $(TMP_IF_1) $(TMP_IF_2) $(DLFCN_INCFLAGS) $(GLOB_INCFLAGS) diff --git a/PROJECTS b/PROJECTS --- a/PROJECTS +++ b/PROJECTS @@ -35,8 +35,6 @@ * Free NLP solver. - * Support for sparse matrices. - * Fix CollocWt to handle Laguerre polynomials. Make it easy to extend it to other polynomial types. @@ -105,6 +103,104 @@ non-square systems compatible with Matlab. Currently, they return the minimum norm solution from DGELSS, which behaves differently. +--------------- +Sparse Matrices: +--------------- + + * Sparse Cholesky factorization for Fchol function and also for the + in built polymorphic solvers. + + * QR factorization functions, also for use in lssolve functions. Write + svds function based on this. Write sprank function based on svds. + + * Once dmperm is implemented, use the technique to detect permuted + triangular matrices. Test the permuted triangular matrix solver code + + * Accelerate the copying of the data from a sparse matrix to a banded matrix + in the solvers, that takes a significant portion of the computation time + for narrow matrices. This is not obvious, due to the treatment of zero + elements in the matrix. Maybe current solution is optimal. + + * Perhaps split the overly long ::solve functions up, either by the type + of solver, or seperate factorization functions, so that they can be + reused in each of 4 different ::solve functions. + + * Sparse inverse function, based on Andy's code from octave-forge. + + * Implement fourth argument to the sprand and sprandn that the leading + brand implements. + + * Mapper functions such as real, imag, abs, etc need to be treated, either + with a dispatch or by changing the mapper function code. + + * Write the rest of the sparse docs + + * The algo in TOMS 582 is perfect for symrcm function. However, this is + under the ACM license and can't be used in a GPL program. + + An alternative is that PETSC is GPL compatiable and has a symrcm + implemented from the original SPARSPAK. Its not clear that this is + legal to me as I have found no clarification of the original license + of SPARSPAK. As PETSC has had this code for over 10 years without + problem, we can perhaps assume that there is no issues. Maybe need + to contact PETSC people or the SPARSPAK people at uni of waterloo + to check issues. + + * Make spalloc(r,c,n) actually create an empty sparse with n non-zero + elements? This allows something like + + sm = spalloc (r,c,n) + for j=1:c + for i=1:r + tmp = foo (i,j); + if (tmp != 0.) + sm (i,j) = tmp; + endif + endfor + endfor + + actually make sense. Otherwise the above will cause massive amounts + of memory reallocation. + + The fact is that this doesn't make sense in any case as the assign + function makes another copy of the sparse matrix. So although spalloc + might easily be made to have the correct behaviour, the first assign + will cause the matrix to be resized !!! There seems to be no simple + way to treat this but a complete rewrite of the sparse assignment + functions... + + * Port the sparse testing code into the DejaGNU testing code. + + * Treat the dispatching of the splu, spdet, functions, etc within octave + itself. This either means that classes need implementing or at the + minimum the octave-forge dispatch function is implemented within octave + + * Other missing Functions + - eigs + - dmperm Tim Davis is apparently working on something + - symmmd Superseded by symamd + - colmmd Superseded by colamd + - sprandsym + - symbfact + - etreeplot + - treeplot + - gplot + - treelayout + - cholinc + - condest + - normest + - bicg + - bicgstab + - cgs + - gmres + - lsqr + - minres + - pcg Can this be taken from o-forge? Is it compatiable + - pcr Can and should this be taken from o-forge? + - qmr + - symmlq + - spaugment + -------- Graphics: -------- diff --git a/doc/ChangeLog b/doc/ChangeLog --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,14 @@ +2005-02-25 John W. Eaton + + Sparse merge. + + 2005-01-07 David Bateman + + * interpreter/sparse.txi: New file. + * interpreter/Makefile.in: Add it to the build. + * interpreter/octave.texi: Include it in the contents tables and the + top level document. + 2005-02-25 John W. Eaton * liboctave/Makefile.in (all): Also depend on Octave-FAQ.pdf. diff --git a/doc/interpreter/Makefile.in b/doc/interpreter/Makefile.in --- a/doc/interpreter/Makefile.in +++ b/doc/interpreter/Makefile.in @@ -25,7 +25,7 @@ grammar.txi image.txi install.txi intro.txi io.txi \ linalg.txi matrix.txi nonlin.txi numbers.txi \ op-idx.txi optim.txi plot.txi poly.txi preface.txi \ - quad.txi quaternion.txi set.txi signal.txi stats.txi \ + quad.txi quaternion.txi set.txi signal.txi sparse.txi stats.txi \ stmt.txi stream.txi strings.txi struct.txi system.txi \ tips.txi var.txi vr-idx.txi diff --git a/doc/interpreter/octave.texi b/doc/interpreter/octave.texi --- a/doc/interpreter/octave.texi +++ b/doc/interpreter/octave.texi @@ -138,6 +138,7 @@ * Arithmetic:: * Linear Algebra:: * Nonlinear Equations:: +* Sparse Matrices:: * Quadrature:: * Differential Equations:: * Optimization:: @@ -378,6 +379,16 @@ * Matrix Factorizations:: * Functions of a Matrix:: +Sparse Matrices + +* Basics:: +* Graph Theory:: +* Sparse Linear Algebra:: +* Iterative Techniques:: +* Oct-Files:: +* License:: +* Function Reference:: + Quadrature * Functions of One Variable:: @@ -507,6 +518,7 @@ @include arith.texi @include linalg.texi @include nonlin.texi +@include sparse.texi @include quad.texi @include diffeq.texi @include optim.texi diff --git a/doc/interpreter/sparse.txi b/doc/interpreter/sparse.txi new file mode 100644 --- /dev/null +++ b/doc/interpreter/sparse.txi @@ -0,0 +1,1308 @@ +@c Copyright (C) 2004, 2005 David Bateman +@c This is part of the Octave manual. +@c For copying conditions, see the file gpl.texi. + +@node Sparse Matrices +@chapter Sparse Matrices + +@menu +* Basics:: The Creation and Manipulation of Sparse Matrices +* Graph Theory:: Graphs are their use with Sparse Matrices +* Sparse Linear Algebra:: Linear Algebra on Sparse Matrices +* Iterative Techniques:: Iterative Techniques applied to Sparse Matrices +* Oct-Files:: Using Sparse Matrices in Oct-files +* License:: Licensing of Third Party Software +* Function Reference:: Documentation from the Specific Sparse Functions +@end menu + +@node Basics, Graph Theory, Sparse Matrices, Sparse Matrices +@section The Creation and Manipulation of Sparse Matrices + +The size of mathematical problems that can be treated at any particular +time is generally limited by the available computing resources. Both, +the speed of the computer and its available memory place limitation on +the problem size. + +There are many classes mathematical problems which give rise to +matrices, where a large number of the elements are zero. In this case +it makes sense to have a special matrix type to handle this class of +problems where only the non-zero elements of the matrix are +stored. Not only done this reduce the amount of memory to store the +matrix, but it also means that operations on this type of matrix can +take advantage of the a-priori knowledge of the positions of the +non-zero elements to accelerate their calculations. + +A matrix type that stores only the non-zero elements is generally called +sparse. It is the purpose of this document to discuss the basics of the +storage and creation of sparse matrices and the fundamental operations +on them. + +THIS DOCUMENT STILL HAS LARGE BLANKS. PLEASE FILL THEM IN. LOOK FOR +THE TAG "WRITE ME" + +@menu +* Storage:: Storage of Sparse Matrices +* Creation:: Creating Sparse Matrices +* Operators and Functions:: Basic Operators and Functions on Sparse Matrices +* Information:: Finding out Information about Sparse Matrices +@end menu + +@node Storage, Creation, Basics, Basics +@subsection Storage of Sparse Matrices + +It is not strictly speaking necessary for the user to understand how +sparse matrices are stored. However, such an understanding will help +to get an understanding of the size of sparse matrices. Understanding +the storage technique is also necessary for those users wishing to +create their own oct-files. + +There are many different means of storing sparse matrix data. What all +of the methods have in common is that they attempt to reduce the compelxity +and storage given a-priori knowledge of the particular class of problems +that will be solved. A good summary of the available techniques for storing +sparse matrix is given by Saad @footnote{Youcef Saad "SPARSKIT: A basic toolkit +for sparse matrix computation", 1994, +@url{ftp://ftp.cs.umn.edu/dept/sparse/SPARSKIT2/DOC/paper.ps}}. +With full matrices, knowledge of the point of an element of the matrix +within the matrix is implied by its position in the computers memory. +However, this is not the case for sparse matrices, and so the positions +of the non-zero elements of the matrix must equally be stored. + +An obvious way to do this is by storing the elements of the matrix as +triplets, with two elements being the of the position in the array +(rows and column) and the third being the data itself. This is conceptually +easy to grasp, but requires more storage than is strictly needed. + +The storage technique used within @sc{Octave} is compressed column +format. In this format the position of each element in a row and the +data are stored as previously. However, if we assume that all elements +in the same column are stored adjacent in the computers memory, then +we only need to store information on the number of non-zero elements +in each column, rather than their positions. Thus assuming that the +matrix has more non-zero elements than there are columns in the +matrix, we win in terms of the amount of memory used. + +In fact, the column index contains one more element than the number of +columns, with the first element always being zero. The advantage of +this is a simplication in the code, in that their is no special case +for the first or last columns. A short example, demonstrating this in +C is. + +@example + for (j = 0; j < nc; j++) + for (i = cidx (j); i < cidx(j+1); i++) + printf ("non-zero element (%i,%i) is %d\n", ridx(i), j, data(i)); +@end example + +A clear understanding might be had by considering an example of how the +above applies to an example matrix. Consider the matrix + +@example +@group + 1 2 0 0 + 0 0 0 3 + 0 0 0 4 +@end group +@end example + +The non-zero elements of this matrix are + +@example +@group + (1, 1) @result{} 1 + (1, 2) @result{} 2 + (2, 4) @result{} 3 + (3, 4) @result{} 4 +@end group +@end example + +This will be stored as three vectors @var{cidx}, @var{ridx} and @var{data}, +representing the column indexing, row indexing and data respectively. The +contents of these three vectors for the above matrix will be + +@example +@group + @var{cidx} = [0, 2, 2, 4] + @var{ridx} = [0, 0, 1, 2] + @var{data} = [1, 2, 3, 4] +@end group +@end example + +Note that this is the representation of these elements with the first row +and column assumed to start as zero. Thus the number of elements in the +@var{i}-th column is given by @code{@var{cidx} (@var{i} + 1) - +@var{cidx} (@var{i})}. + +It should be noted that compressed row formats are equally possible. However, +in the context of mixed operations between mixed sparse and dense matrices, +it makes sense that the elements of the sparse matrices are in the same +order as the dense matrices. @sc{Octave} stores dense matrices in column +major ordering, and so sparse matrices are equally stored in this manner. + +A further constraint on the sparse matrix storage used by @sc{Octave} is that +all elements in the rows are stored in increasing order of their row +index. This makes certain operations, later be faster. However, it imposes +the need to sort the elements on the creation of sparse matrices. Having +dis-ordered elements is potentially an advantage in that it makes operations +such as concatenating two sparse matrices together easier and faster, however +it adds complexity and speed problems elsewhere. + +@node Creation, Operators and Functions, Storage, Basics +@subsection Creating Sparse Matrices + +There are several means to create sparse matrix. + +@table @asis +@item Returned from a function +There are many functions that directly return sparse matrices. These include +@dfn{speye}, @dfn{sprand}, @dfn{spdiag}, etc. +@item Constructed from matrices or vectors +The function @dfn{sparse} allows a sparse matrix to be constructed from +three vectors representing the row, column and data. ALternatively, the +function @dfn{spconvert} uses a three column matrix format to allow easy +importation of data from elsewhere. +@item Created and then filled +The function @dfn{sparse} or @dfn{spalloc} can be used to create an empty +matrix that is then filled by the user +@item From a user binary program +The user can directly create the sparse matrix within an oct-file. +@end table + +There are several basic functions to return specific sparse +matrices. For example the sparse identity matrix, is a matrix that is +often needed. It therefore has its own function to create it as +@code{speye (@var{n})} or @code{speye (@var{r}, @var{c})}, which +creates an @var{n}-by-@var{n} or @var{r}-by-@var{c} sparse identity +matrix. + +Another typical sparse matrix that is often needed is a random distribution +of random elements. The functions @dfn{sprand} and @dfn{sprandn} perform +this for uniform and random distributions of elements. They have exactly +the same calling convention as @code{sprand (@var{r}, @var{c}, @var{d})}, +which creates an @var{r}-by-@var{c} sparse matrix a density of filled +elements of @var{d}. + +Other functions of interest that directly creates a sparse matrix, are +@dfn{spdiag} or its generalization @dfn{spdiags}, that can take the +definition of the diagonals of the matrix and create the sparse matrix +that corresponds to this. For example + +@c FIXME, when spdiag is overloaded to diag the below won't work. + +@example +s = spdiag (randn(1,n), -1); +@end example + +creates a sparse (@var{n}+1)-by-(@var{n}+1) sparse matrix with a single +diagonal defined. + +The recommended way for the user to create a sparse matrix, is to create +two vectors contain the row and column index of the data and a third +vector of the same size containing the data to be stored. For example + +@example + function x = foo (r, j) + idx = randperm (r); + x = ([zeros(r-2,1); rand(2,1)])(idx); + endfunction + + ri = []; + ci = []; + d = []; + + for j=1:c + dtmp = foo (r, j); # Returns vector of length r with (:,j) values + idx = find (dtmp != 0.); + ri = [ri; idx]; + ci = [ci; j*ones(length(idx),1)]; + d = [d; dtmp(idx)]; + endfor + s = sparse (ri, ci, d, r, c); +@end example + +creates an @var{r}-by-@var{c} sparse matrix with a random distribution of +2 elements per row. The elements of the vectors do not need to be sorted in +any particular order as @sc{Octave} will store them prior to storing the +data. However, per sorting the data will make teh creation of the sparse +matrix faster. + +The function @dfn{spconvert} takes a three or four column real matrix. +The first two columns represent the row and column index respectively and +the third and four columns, the real and imaginary parts of the sparse +matrix. The matrix can contain zero elements and the elements can be +sorted in any order. Adding zero elements is a convenient way to define +the size of the sparse matrix. For example + +@example +s = spconvert ([1 2 3 4; 1 3 4 4; 1 2 3 0]') +@result{} Compressed Column Sparse (rows=4, cols=4, nnz=3) + (1 , 1) -> 1 + (2 , 3) -> 2 + (3 , 4) -> 3 +@end example + +An example of creating and filling a matrix might be + +@example +k = 5; +nz = r * k; +s = spalloc (r, c, nz) +for j = 1:c + idx = randperm (r); + s (:, j) = [zeros(r - k, 1); rand(k, 1)] (idx); +endfor +@end example + +It should be noted, that due to the way that the @sc{Octave} +assignment functions are written that the assignment will reallocate +the memory used by the sparse matrix at each iteration. Therefore the +@dfn{spalloc} function ignores the @var{nz} argument and does not +preassign the memory for the matrix. Therefore, it is vitally +important that code using to above structure should be as vectorized +as possible to minimize the number of assignments and reduce the +number of memory allocations. + +The above problem can be avoided in oct-files. However, the +construction of a sparse matrix from an oct-file is more complex than +can be discussed in this brief introduction, and you are referred to +section @ref{Oct-Files}, to have a full description of the techniques +involved. + +@node Operators and Functions, Information, Creation, Basics +@subsection Basic Operators and Functions on Sparse Matrices + +@menu +* Functions:: Operators and Functions +* ReturnType:: The Return Types of Operators and Functions +* MathConsiderations:: Mathematical Considerations +@end menu + +@node Functions, ReturnType, Operators and Functions, Operators and Functions +@subsubsection Operators and Functions + +WRITE ME + +@node ReturnType, MathConsiderations, Functions, Operators and Functions +@subsubsection The Return Types of Operators and Functions + +The two basic reason to use sparse matrices are to reduce the memory +usage and to not have to do calculations on zero elements. The two are +closely related in that the computation time on a sparse matrix operator +or function is roughly linear with the numberof non-zero elements. + +Therefore, there is a certain density of non-zero elements of a matrix +where it no longer makes sense to store it as a sparse matrix, but rather +as a full matrix. For this reason operators and functions that have a +high probability of returning a full matrix will always return one. For +example adding a scalar constant to a sparse matrix will almost always +make it a full matrix, and so the example + +@example +speye(3) + 0 +@result{} 1 0 0 + 0 1 0 + 0 0 1 +@end example + +returns a full matrix as can be seen. Additionally all sparse functions +test the amount of memory occupied by the sparse matrix to see if the +amount of storage used is larger than the amount used by the full +equivalent. Therefore @code{speye (2) * 1} will return a full matrix as +the memory used is smaller for the full version than the sparse version. + +As all of the mixed operators and functions between full and sparse +matrices exist, in general this does not cause any problems. However, +one area where it does cause a problem is where a sparse matrix is +promoted to a full matrix, where subsequent operations would resparsify +the matrix. Such cases as rare, but can be artificially created, for +example @code{(fliplr(speye(3)) + speye(3)) - speye(3)} gives a full +matrix when it should give a sparse one. In general, where such cases +occur, they impose only a small memory penalty. + +There is however one known case where this behaviour of @sc{Octave}'s +sparse matrices will cause a problem. That is in the handling of the +@dfn{diag} function. Whether @dfn{diag} returns a sparse or full matrix +depending on the type of its input arguments. So + +@example + a = diag (sparse([1,2,3]), -1); +@end example + +should return a sparse matrix. To ensure this actually happens, the +@dfn{sparse} function, and other functions based on it like @dfn{speye}, +always returns a sparse matrix, even if the memory used will be larger +than its full representation. + +@node MathConsiderations, , ReturnType, Operators and Functions +@subsubsection Mathematical Considerations + +The attempt has been made to make sparse matrices behave in exactly the +same manner as there full counterparts. However, there are certain differences +and especially differences with other products sparse implementations. + +Firstly, the "./" and ".^" operators must be used with care. Consider what +the examples + +@example + s = speye (4); + a1 = s .^ 2; + a2 = s .^ s; + a3 = s .^ -2; + a4 = s ./ 2; + a5 = 2 ./ s; + a6 = s ./ s; +@end example + +will give. The first example of @var{s} raised to the power of 2 causes +no problems. However @var{s} raised element-wise to itself involves a +a large number of terms @code{0 .^ 0} which is 1. There @code{@var{s} .^ +@var{s}} is a full matrix. + +Likewise @code{@var{s} .^ -2} involves terms terms like @code{0 .^ -2} which +is infinity, and so @code{@var{s} .^ -2} is equally a full matrix. + +For the "./" operator @code{@var{s} ./ 2} has no problems, but +@code{2 ./ @var{s}} involves a large number of infinity terms as well +and is equally a full matrix. The case of @code{@var{s} ./ @var{s}} +involves terms like @code{0 ./ 0} which is a @code{NaN} and so this +is equally a full matrix with the zero elements of @var{s} filled with +@code{NaN} values. + +The above behaviour is consistent with full matrices, but is not +consistent with sparse implementations in other products. + +A particular problem of sparse matrices comes about due to the fact that +as the zeros are not stored, the sign-bit of these zeros is equally not +stored... In certain cases the sign-bit of zero is important. For example + +@example + a = 0 ./ [-1, 1; 1, -1]; + b = 1 ./ a + @result{} -Inf Inf + Inf -Inf + c = 1 ./ sparse (a) + @result{} Inf Inf + Inf Inf +@end example + +To correct this behaviour would mean that zero elements with a negative +sign-bit would need to be stored in the matrix to ensure that their +sign-bit was respected. This is not done at this time, for reasons of +efficient, and so the user is warned that calculations where the sign-bit +of zero is important must not be done using sparse matrices. + +Also discuss issues of fill-in. Discuss symamd etc, and mention randperm +that is included elsewhere in the docs... + +WRITE ME + +@node Information, , Operators and Functions, Basics +@subsection Finding out Information about Sparse Matrices + +Talk about the spy, spstats, nnz, spparms, etc function + +WRITE ME + +@node Graph Theory, Sparse Linear Algebra, Basics, Sparse Matrices +@section Graphs are their use with Sparse Matrices + +Someone who knows more about this than me should write this... + +WRITE ME + +@node Sparse Linear Algebra, Iterative Techniques, Graph Theory, Sparse Matrices +@section Linear Algebra on Sparse Matrices + +@sc{Octave} includes a poly-morphic solver for sparse matrices, where +the exact solver used to factorize the matrix, depends on the properties +of the sparse matrix, itself. As the cost of determining the matrix type +is small relative to the cost of factorizing the matrix itself, the matrix +type is re-determined each time it is used in a linear equation. + +The selection tree for how the linear equation is solve is + +@enumerate 1 +@item If the matrix is not square go to 9. + +@item If the matrix is diagonal, solve directly and goto 9 + +@item If the matrix is a permuted diagonal, solve directly taking into +account the permutations. Goto 9 + +@item If the matrix is banded and if the band density is less than that +given by @code{spparms ("bandden")} continue, else goto 5. + +@enumerate a +@item If the matrix is tridiagonal and the right-hand side is not sparse +continue, else goto 4b. + +@enumerate +@item If the matrix is hermitian, with a positive real diagonal, attempt + Cholesky factorization using @sc{Lapack} xPTSV. + +@item If the above failed or the matrix is not hermitian with a positive + real diagonal use Gaussian elimination with pivoting using + @sc{Lapack} xGTSV, and goto 9. +@end enumerate + +@item If the matrix is hermitian with a positive real diagonal, attempt + Cholesky factorization using @sc{Lapack} xPBTRF. + +@item if the above failed or the matrix is not hermitian with a positive + real diagonal use Gaussian elimination with pivoting using + @sc{Lapack} xGBTRF, and goto 9. +@end enumerate + +@item If the matrix is upper or lower triangular perform a sparse forward +or backward subsitution, and goto 9 + +@item If the matrix is a permuted upper or lower triangular matrix, perform +a sparse forward or backward subsitution, and goto 9 + +FIXME: Detection of permuted triangular matrices not written yet, and so + the code itself is not tested either + +@item If the matrix is hermitian with a real positive diagonal, attempt +sparse Cholesky factorization. + +FIXME: Detection of positive definite matrices written and tested, but + Cholesky factorization isn't yet written + +@item If the sparse Cholesky factorization failed or the matrix is not +hermitian with a real positive diagonal, factorize using UMFPACK. + +@item If the matrix is not square, or any of the previous solvers flags +a singular or near singular matrix, find a minimum norm solution + +FIXME: QR solvers not yet written. + +@end enumerate + +The band density is defined as the number of non-zero values in the matrix +divided by the number of non-zero values in the matrix. The banded matrix +solvers can be entirely disabled by using @dfn{spparms} to set @code{bandden} +to 1 (i.e. @code{spparms ("bandden", 1)}). + +All of the solvers above, expect the banded solvers, calculate an +estimate of the condition number. This can be used to detect numerical +stability problems in the solution and force a minimum norm solution +to be used. However, for narrow banded matrices, the cost of +calculating the condition number is significant, and can in fact exceed +the cost of factoring the matrix. Therefore the condition number is +not calculated for banded matrices, and therefore unless the factorization +is exactly singular, these numerical instabilities won't be detected. +In cases where, this might be a problem the user is recommended to disable +the banded solvers as above, at a significant cost in terms of speed. + +@node Iterative Techniques, Oct-Files, Sparse Linear Algebra, Sparse Matrices +@section Iterative Techniques applied to sparse matrices + +WRITE ME + +@node Oct-Files, License, Iterative Techniques, Sparse Matrices +@section Using Sparse Matrices in Oct-files + +An oct-file is a means of writing an @sc{Octave} function in a compilable +language like C++, rather than as a script file. This results in a +significant acceleration in the code. It is not the purpose of this +section to discuss how to write an oct-file, or discuss what they +are. There are already two @footnote{Paul Thomas "Dal Segno al Coda +- The octave dynamically linked function cookbook", +@url{http://perso.wanadoo.fr/prthomas/intro.html}, and Cristophe Spiel +"Del Coda Al Fine - Pushing Octave's Limits", +@url{http://octave.sourceforge.net/coda/coda.pdf}} very good +references on oct-files themselves. Users who are not familiar with +oct-files are urged to read these references to fully understand this +chapter. The examples discussed here assume that the oct-file is written +entirely in C++. + +There are three classes of sparse objects that are of interest to the +user. + +@table @asis +@item SparseMatrix +A double precision sparse matrix class +@item SparseComplexMatrix +A Complex sparse matrix class +@item SparseBoolMatrix +A boolen sparse matrix class +@end table + +All of these classes inherit from the @code{Sparse} template class, +and so all have similar capabilities and usage. The @code{Sparse} +class was based on @sc{Octave} @code{Array} class, and so users familar +with @sc{Octave}'s Array classes will be comfortable with the use of +the sparse classes. + +The sparse classes will not be entirely described in this section, due +to their similar with the existing Array classes. However, there are a +few differences due the different nature of sparse objects, and these +will be described. Firstly, although it is fundamentally possible to +have N-dimensional sparse objects, the @sc{Octave} sparse classes do +not allow them at this time. So all operations of the sparse classes +must be 2-dimensional. This means that in fact @code{SparseMatrix} is +similar to @sc{Octave}'s @code{Matrix} class rather than its +@code{NDArray} class. + +@menu +* OctDifferences:: The Differences between the Array and Sparse Classes +* OctCreation:: Creating Spare Matrices in Oct-Files +* OctUse:: Using Sparse Matrices in Oct-Files +@end menu + +@node OctDifferences, OctCreation, Oct-Files, Oct-Files +@subsection The Differences between the Array and Sparse Classes + +The number of elements in a sparse matrix is considered to be the number +of non-zero elements rather than the product of the dimensions. Therefore + +@example + SparseMatrix sm; + @dots{} + int nel = sm.nelem (); +@end example + +returns the number of non-zero elements. If the user really requires the +number of elements in the matrix, including the non-zero elements, they +should use @code{numel} rather than @code{nelem}. Note that for very +large matrices, where the product of the two dimensions is large that +the representation of the an unsigned int, then @code{numel} can overflow. +An example is @code{speye(1e6)} which will create a matrix with a million +rows and columns, but only a million non-zero elements. Therefore the +number of rows by the number of columns in this case is more than two +hundred times the maximum value that can be represented by an unsigned int. +The use of @code{numel} should therefore be avoided useless it is known +it won't overflow. + +Extreme care must be take with the elem method and the "()" operator, +which perform basically the same function. The reason is that if a +sparse object is non-const, then @sc{Octave} will assume that a +request for a zero element in a sparse matrix is in fact a request +to create this element so it can be filled. Therefore a piece of +code like + +@example + SparseMatrix sm; + @dots{} + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + std::cerr << " (" << i << "," << j << "): " << sm(i,j) + << std::endl; +@end example + +is a great way of turning the sparse matrix into a dense one, and a +very slow way at that since it reallocates the sparse object at each +zero element in the matrix. + +An easy way of preventing the above from hapening is to create a temporary +constant version of the sparse matrix. Note that only the container for +the sparse matrix will be copied, while the actual representation of the +data will be shared between the two versions of the sparse matrix. So this +is not a costly operation. For example, the above would become + +@example + SparseMatrix sm; + @dots{} + const SparseMatrix tmp (sm); + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + std::cerr << " (" << i << "," << j << "): " << tmp(i,j) + << std::endl; +@end example + +Finally, as the sparse types aren't just represented as a contiguous +block of memory, the @code{fortran_vec} method of the @code{Array} +is not available. It is however replaced by three seperate methods +@code{ridx}, @code{cidx} and @code{data}, that access the raw compressed +column format that the @sc{Octave} sparse matrices are stored in. +Additionally, these methods can be used in a manner similar to @code{elem}, +to allow the matrix to be accessed or filled. However, in that case it is +up to the user to repect the sparse matrix compressed column format +discussed previous. + +@node OctCreation, OctUse, OctDifferences, Oct-Files +@subsection Creating Spare Matrices in Oct-Files + +The user has several alternatives in how to create a sparse matrix. +They can first create the data as three vectors representing the +row and column indexes and the data, and from those create the matrix. +Or alternatively, they can create a sparse matrix with the appropriate +amount of space and then fill in the values. Both techniques have their +advantages and disadvantages. + +An example of how to create a small sparse matrix with the first technique +might be seen the example + +@example + int nz = 4, nr = 3, nc = 4; + ColumnVector ridx (nz); + ColumnVector cidx (nz); + ColumnVector data (nz); + + ridx(0) = 0; ridx(1) = 0; ridx(2) = 1; ridx(3) = 2; + cidx(0) = 0; cidx(1) = 1; cidx(2) = 3; cidx(3) = 3; + data(0) = 1; data(1) = 2; data(2) = 3; data(3) = 4; + + SparseMatrix sm (data, ridx, cidx, nr, nc); +@end example + +which creates the matrix given in section @ref{Storage}. Note that +the compressed matrix format is not used at the time of the creation +of the matrix itself, however it is used internally. + +As previously mentioned, the values of the sparse matrix are stored +in increasing column-major ordering. Although the data passed by the +user does not need to respect this requirement, the pre-sorting the +data significantly speeds up the creation of the sparse matrix. + +The disadvantage of this technique of creating a sparse matrix is +that there is a brief time where two copies of the data exists. Therefore +for extremely memory constrained problems this might not be the right +technique to create the sparse matrix. + +The alternative is to first create the sparse matrix with the desired +number of non-zero elements and then later fill those elements in. The +easiest way to do this is + +@example + int nz = 4, nr = 3, nc = 4; + SparseMatrix sm (nr, nc, nz); + sm(0,0) = 1; sm(0,1) = 2; sm(1,3) = 3; sm(2,3) = 4; +@end example + +That creates the same matrix as previously. Again, although it is not +strictly necessary, it is significantly faster if the sparse matrix is +created in this manner that the elements are added in column-major +ordering. The reason for this is that if the elements are inserted +at the end of the current list of known elements then no element +in the matrix needs to be moved to allow the new element to be +inserted. Only the column indexes need to be updated. + +There are a few further points to note about this technique of creating +a sparse matrix. Firstly, it is not illegal to create a sparse matrix +with fewer elements than are actually inserted in the matrix. Therefore + +@example + int nz = 4, nr = 3, nc = 4; + SparseMatrix sm (nr, nc, 0); + sm(0,0) = 1; sm(0,1) = 2; sm(1,3) = 3; sm(2,3) = 4; +@end example + +is perfectly legal. However it is a very bad idea. The reason is that +as each new element is added to the sparse matrix the space allocated +to it is increased by reallocating the memory. This is an expensive +operation, that will significantly slow this means of creating a sparse +matrix. Furthermore, it is not illegal to create a sparse matrix with +too much storage, so having @var{nz} above equaling 6 is also legal. +The disadvantage is that the matrix occupies more memory than strictly +needed. + +It is not always easy to known the number of non-zero elements prior +to filling a matrix. For this reason the additional storage for the +sparse matrix can be removed after its creation with the +@dfn{maybe_compress} function. Furthermore, the maybe_compress can +deallocate the unused storage, but it can equally remove zero elements +from the matrix. The removal of zero elements from the matrix is +controlled by setting the argument of the @dfn{maybe_compress} function +to be 'true'. However, the cost of removing the zeros is high because it +implies resorting the elements. Therefore, if possible it is better +is the user doesn't add the zeros in the first place. An example of +the use of @dfn{maybe_compress} is + +@example + int nz = 6, nr = 3, nc = 4; + SparseMatrix sm1 (nr, nc, nz); + sm1(0,0) = 1; sm1(0,1) = 2; sm1(1,3) = 3; sm1(2,3) = 4; + sm1.maybe_compress (); // No zero elements were added + + SparseMatrix sm2 (nr, nc, nz); + sm2(0,0) = 1; sm2(0,1) = 2; sm(0,2) = 0; sm(1,2) = 0; + sm1(1,3) = 3; sm1(2,3) = 4; + sm2.maybe_compress (true); // Zero elements were added +@end example + +The use of the @dfn{maybe_compress} function should be avoided if +possible, as it will slow the creation of the matrices. + +A third means of creating a sparse matrix is to work directly with +the data in compressed row format. An example of this technique might +be + +@c Note the @verbatim environment is a relatively new addition to texinfo. +@c Therefore use the @example environment and replace @, with @@, +@c { with @{, etc + +@example + octave_value arg; + + @dots{} + + int nz = 6, nr = 3, nc = 4; // Assume we know the max no nz + SparseMatrix sm (nr, nc, nz); + Matrix m = arg.matrix_value (); + + int ii = 0; + sm.cidx (0) = 0; + for (int j = 1; j < nc; j++) + @{ + for (int i = 0; i < nr; i++) + @{ + double tmp = foo (m(i,j)); + if (tmp != 0.) + @{ + sm.data(ii) = tmp; + sm.ridx(ii) = i; + ii++; + @} + @} + sm.cidx(j+1) = ii; + @} + sm.maybe_mutate (); // If don't know a-priori the final no of nz. +@end example + +which is probably the most efficient means of creating the sparse matrix. + +Finally, it might sometimes arise that the amount of storage initially +created is insufficient to completely store the sparse matrix. Therefore, +the method @code{change_capacity} exists to reallocate the sparse memory. +The above example would then be modified as + +@example + octave_value arg; + + @dots{} + + int nz = 6, nr = 3, nc = 4; // Assume we know the max no nz + SparseMatrix sm (nr, nc, nz); + Matrix m = arg.matrix_value (); + + int ii = 0; + sm.cidx (0) = 0; + for (int j = 1; j < nc; j++) + @{ + for (int i = 0; i < nr; i++) + @{ + double tmp = foo (m(i,j)); + if (tmp != 0.) + @{ + if (ii == nz) + @{ + nz += 2; // Add 2 more elements + sm.change_capacity (nz); + @} + sm.data(ii) = tmp; + sm.ridx(ii) = i; + ii++; + @} + @} + sm.cidx(j+1) = ii; + @} + sm.maybe_mutate (); // If don't know a-priori the final no of nz. +@end example + +Note that both increasing and decreasing the number of non-zero elements in +a sparse matrix is expensive, as it involves memory reallocation. Also as +parts of the matrix, though not its entirety, exist as the old and new copy +at the same time, additional memory is needed. Therefore if possible this +should be avoided. + +@node OctUse, , OctCreation, Oct-Files +@subsection Using Sparse Matrices in Oct-Files + +Most of the same operators and functions on sparse matrices that are +available from the @sc{Octave} are equally available with oct-files. +The basic means of extracting a sparse matrix from an @code{octave_value} +and returning them as an @code{octave_value}, can be seen in the +following example + +@example + octave_value_list retval; + + SparseMatrix sm = args(0).sparse_matrix_value (); + SparseComplexMatrix scm = args(1).sparse_complex_matrix_value (); + SparseBoolMatrix sbm = args(2).sparse_bool_matrix_value (); + + @dots{} + + retval(2) = sbm; + retval(1) = scm; + retval(0) = sm; +@end example + +The conversion to an octave-value is handled by the sparse +@code{octave_value} constructors, and so no special care is needed. + +@node License, Function Reference, Oct-Files, Sparse Matrices +@section Licensing of Third Party Software + +There are several third party software packages used by the @sc{Octave} +sparse matrix. + +@table @asis +@item COLAMD +is used for the @dfn{colamd} and @dfn{symamd} functions. + +@table @asis +@item Authors +The authors of the code itself are Stefan I. Larimore and Timothy A. +Davis (davis@@cise.ufl.edu), University of Florida. The algorithm was +developed in collaboration with John Gilbert, Xerox PARC, and Esmond +Ng, Oak Ridge National Laboratory. + +@item License +Copyright @copyright{} 1998-2003 by the University of Florida. +All Rights Reserved. + +THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + +Permission is hereby granted to use, copy, modify, and/or distribute +this program, provided that the Copyright, this License, and the +Availability of the original version is retained on all copies and made +accessible to the end-user of any code or package that includes COLAMD +or any modified version of COLAMD. + +@item Availability +@url{http://www.cise.ufl.edu/research/sparse/colamd/} +@end table + +@item UMFPACK +is used in various places with the sparse types, including the +LU decomposition and solvers. + +@table @asis +@item License +UMFPACK Version 4.3 (Jan. 16, 2004), Copyright @copyright{} 2004 by +Timothy A. Davis. All Rights Reserved. + +Your use or distribution of UMFPACK or any modified version of +UMFPACK implies that you agree to this License. + +THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + +Permission is hereby granted to use or copy this program, provided +that the Copyright, this License, and the Availability of the original +version is retained on all copies. User documentation of any code that +uses UMFPACK or any modified version of UMFPACK code must cite the +Copyright, this License, the Availability note, and 'Used by permission.' +Permission to modify the code and to distribute modified code is granted, +provided the Copyright, this License, and the Availability note are +retained, and a notice that the code was modified is included. This +software was developed with support from the National Science Foundation, +and is provided to you free of charge. + +@item Availability +@url{http://www.cise.ufl.edu/research/sparse/umfpack/} +@end table +@end table + +@node Function Reference, , License, Sparse Matrices +@section Function Reference + +@iftex +@subsection Functions by Category +@subsubsection Generate sparse matrix +@table @asis +@item spdiags +A generalization of the function `spdiag'. +@item speye +Returns a sparse identity matrix. +@item sprand +Generate a random sparse matrix. +@item sprandn +Generate a random sparse matrix. +@item sprandsym +@emph{Not implemented} +@end table +@subsubsection Sparse matrix conversion +@table @asis +@item full +returns a full storage matrix from a sparse one See also: sparse +@item sparse +SPARSE: create a sparse matrix +@item spconvert +This function converts for a simple sparse matrix format easily produced by other programs into Octave's internal sparse format. +@item spfind +SPFIND: a sparse version of the find operator 1. +@end table +@subsubsection Manipulate sparse matrices +@table @asis +@item issparse +Return 1 if the value of the expression EXPR is a sparse matrix. +@item nnz +returns number of non zero elements in SM See also: sparse +@item nonzeros +Returns a vector of the non-zero values of the sparse matrix S +@item nzmax +Returns the amount of storage allocated to the sparse matrix SM. +@item spalloc +Returns an empty sparse matrix of size R-by-C. +@item spfun +Compute `f(X)' for the non-zero values of X This results in a sparse matrix with the same structure as X. +@item spones +Replace the non-zero entries of X with ones. +@item spy +Plot the sparsity pattern of the sparse matrix X +@end table +@subsubsection Graph Theory +@table @asis +@item etree +Returns the elimination tree for the matrix S. +@item etreeplot +@emph{Not implemented} +@item gplot +@emph{Not implemented} +@item treelayout +@emph{Not implemented} +@item treeplot +@emph{Not implemented} +@end table +@subsubsection Sparse matrix reordering +@table @asis +@item colamd +Column approximate minimum degree permutation. +@item colperm +Returns the column permutations such that the columns of `S (:, P)' are ordered in terms of increase number of non-zero elements. +@item dmperm +Perfrom a Deulmage-Mendelsohn permutation on the sparse matrix S. +@item symamd +For a symmetric positive definite matrix S, returns the permutation vector p such that `S (P, P)' tends to have a sparser Cholesky factor than S. +@item symrcm +Returns the Reverse Cuthill McKee reordering of the sparse matrix S. +@end table +@subsubsection Linear algebra +@table @asis +@item cholinc +@emph{Not implemented} +@item condest +@emph{Not implemented} +@item eigs +@emph{Not implemented} +@item normest +@emph{Not implemented} +@item spdet +Compute the determinant of sparse matrix A using UMFPACK. +@item spinv +Compute the inverse of the square matrix A. +@item splu +Compute the LU decomposition of the sparse matrix A, using subroutines from UMFPACK. +@item sprank +@emph{Not implemented} +@item svds +@emph{Not implemented} +@end table +@subsubsection Iterative techniques +@table @asis +@item bicg +@emph{Not implemented} +@item bicgstab +@emph{Not implemented} +@item cgs +@emph{Not implemented} +@item gmres +@emph{Not implemented} +@item lsqr +@emph{Not implemented} +@item minres +@emph{Not implemented} +@item pcg +@emph{Not implemented} +@item pcr +@emph{Not implemented} +@item qmr +@emph{Not implemented} +@item symmlq +@emph{Not implemented} +@end table +@subsubsection Miscellaneous +@table @asis +@item spaugment +@emph{Not implemented} +@item spparms +Sets or displays the parameters used by the sparse solvers and factorization functions. +@item symbfact +Performs a symbolic factorization analysis on the sparse matrix S. +@item spstats +Return the stats for the non-zero elements of the sparse matrix S COUNT is the number of non-zeros in each column, MEAN is the mean of the non-zeros in each column, and VAR is the variance of the non-zeros in each column +@item spprod +Product of elements along dimension DIM. +@item spcumprod +Cumulative product of elements along dimension DIM. +@item spcumsum +Cumulative sum of elements along dimension DIM. +@item spsum +Sum of elements along dimension DIM. +@item spsumsq +Sum of squares of elements along dimension DIM. +@item spmin +For a vector argument, return the minimum value. +@item spmax +For a vector argument, return the maximum value. +@item spatan2 +Compute atan (Y / X) for corresponding sparse matrix elements of Y and X. +@item spdiag +Return a diagonal matrix with the sparse vector V on diagonal K. +@item spreshape +Return a sparse matrix with M rows and N columns whose elements are taken from the sparse matrix A. +@end table + +@subsection Functions Alphabetically +@end iftex + +@menu +* colamd:: Column approximate minimum degree permutation. +* colperm:: Returns the column permutations such that the columns of `S + (:, P)' are ordered in terms of increase number of non-zero + elements. +* dmperm:: Perfrom a Deulmage-Mendelsohn permutation on the sparse + matrix S. +* etree:: Returns the elimination tree for the matrix S. +* full:: returns a full storage matrix from a sparse one See also: + sparse +* issparse:: Return 1 if the value of the expression EXPR is a sparse + matrix. +* nnz:: returns number of non zero elements in SM See also: sparse +* nonzeros:: Returns a vector of the non-zero values of the sparse + matrix S +* nzmax:: Returns the amount of storage allocated to the sparse + matrix SM. +* spalloc:: Returns an empty sparse matrix of size R-by-C. +* sparse:: SPARSE: create a sparse matrix +* spatan2:: Compute atan (Y / X) for corresponding sparse matrix + elements of Y and X. +* spconvert:: This function converts for a simple sparse matrix format + easily produced by other programs into Octave's internal + sparse format. +* spcumprod:: Cumulative product of elements along dimension DIM. +* spcumsum:: Cumulative sum of elements along dimension DIM. +* spdet:: Compute the determinant of sparse matrix A using UMFPACK. +* spdiag:: Return a diagonal matrix with the sparse vector V on + diagonal K. +* spdiags:: A generalization of the function `spdiag'. +* speye:: Returns a sparse identity matrix. +* spfind:: SPFIND: a sparse version of the find operator 1. +* spfun:: Compute `f(X)' for the non-zero values of X This results in + a sparse matrix with the same structure as X. +* spinv:: Compute the inverse of the square matrix A. +* splu:: Compute the LU decomposition of the sparse matrix A, using + subroutines from UMFPACK. +* spmax:: For a vector argument, return the maximum value. +* spmin:: For a vector argument, return the minimum value. +* spones:: Replace the non-zero entries of X with ones. +* spparms:: Sets or displays the parameters used by the sparse solvers + and factorization functions. +* spprod:: Product of elements along dimension DIM. +* sprand:: Generate a random sparse matrix. +* sprandn:: Generate a random sparse matrix. +* spreshape:: Return a sparse matrix with M rows and N columns whose + elements are taken from the sparse matrix A. +* spstats:: Return the stats for the non-zero elements of the sparse + matrix S COUNT is the number of non-zeros in each column, + MEAN is the mean of the non-zeros in each column, and VAR + is the variance of the non-zeros in each column +* spsum:: Sum of elements along dimension DIM. +* spsumsq:: Sum of squares of elements along dimension DIM. +* spy:: Plot the sparsity pattern of the sparse matrix X +* symamd:: For a symmetric positive definite matrix S, returns the + permutation vector p such that `S (P, P)' tends to have a + sparser Cholesky factor than S. +* symbfact:: Performs a symbolic factorization analysis on the sparse + matrix S. +* symrcm:: Returns the Reverse Cuthill McKee reordering of the sparse + matrix S. +@end menu + +@node colamd, colperm, , Function Reference +@subsubsection colamd + +@DOCSTRING(colamd) + +@node colperm, dmperm, colamd, Function Reference +@subsubsection colperm + +@DOCSTRING(colperm) + +@node dmperm, etree, colperm, Function Reference +@subsubsection dmperm + +@DOCSTRING(dmperm) + +@node etree, full, dmperm, Function Reference +@subsubsection etree + +@DOCSTRING(etree) + +@node full, issparse, etree, Function Reference +@subsubsection full + +@DOCSTRING(full) + +@node issparse, nnz, full, Function Reference +@subsubsection issparse + +@DOCSTRING(issparse) + +@node nnz, nonzeros, issparse, Function Reference +@subsubsection nnz + +@DOCSTRING(nnz) + +@node nonzeros, nzmax, nnz, Function Reference +@subsubsection nonzeros + +@DOCSTRING(nonzeros) + +@node nzmax, spalloc, nonzeros, Function Reference +@subsubsection nzmax + +@DOCSTRING(nzmax) + +@node spalloc, sparse, nzmax, Function Reference +@subsubsection spalloc + +@DOCSTRING(spalloc) + +@node sparse, spatan2, spalloc, Function Reference +@subsubsection sparse + +@DOCSTRING(sparse) + +@node spatan2, spconvert, sparse, Function Reference +@subsubsection spatan2 + +@DOCSTRING(spatan2) + +@node spconvert, spcumprod, spatan2, Function Reference +@subsubsection spconvert + +@DOCSTRING(spconvert) + +@node spcumprod, spcumsum, spconvert, Function Reference +@subsubsection spcumprod + +@DOCSTRING(spcumprod) + +@node spcumsum, spdet, spcumprod, Function Reference +@subsubsection spcumsum + +@DOCSTRING(spcumsum) + +@node spdet, spdiag, spcumsum, Function Reference +@subsubsection spdet + +@DOCSTRING(spdet) + +@node spdiag, spdiags, spdet, Function Reference +@subsubsection spdiag + +@DOCSTRING(spdiag) + +@node spdiags, speye, spdiag, Function Reference +@subsubsection spdiags + +@DOCSTRING(spdiags) + +@node speye, spfind, spdiags, Function Reference +@subsubsection speye + +@DOCSTRING(speye) + +@node spfind, spfun, speye, Function Reference +@subsubsection spfind + +@DOCSTRING(spfind) + +@node spfun, spinv, spfind, Function Reference +@subsubsection spfun + +@DOCSTRING(spfun) + +@node spinv, splu, spfun, Function Reference +@subsubsection spinv + +@DOCSTRING(spinv) + +@node splu, spmax, spinv, Function Reference +@subsubsection splu + +@DOCSTRING(splu) + +@node spmax, spmin, splu, Function Reference +@subsubsection spmax + +@DOCSTRING(spmax) + +@node spmin, spones, spmax, Function Reference +@subsubsection spmin + +@DOCSTRING(spmin) + +@node spones, spparms, spmin, Function Reference +@subsubsection spones + +@DOCSTRING(spones) + +@node spparms, spprod, spones, Function Reference +@subsubsection spparms + +@DOCSTRING(spparms) + +@node spprod, sprand, spparms, Function Reference +@subsubsection spprod + +@DOCSTRING(spprod) + +@node sprand, sprandn, spprod, Function Reference +@subsubsection sprand + +@DOCSTRING(sprand) + +@node sprandn, spreshape, sprand, Function Reference +@subsubsection sprandn + +@DOCSTRING(sprandn) + +@node spreshape, spstats, sprandn, Function Reference +@subsubsection spreshape + +@DOCSTRING(spreshape) + +@node spstats, spsum, spreshape, Function Reference +@subsubsection spstats + +@DOCSTRING(spstats) + +@node spsum, spsumsq, spstats, Function Reference +@subsubsection spsum + +@DOCSTRING(spsum) + +@node spsumsq, spy, spsum, Function Reference +@subsubsection spsumsq + +@DOCSTRING(spsumsq) + +@node spy, symamd, spsumsq, Function Reference +@subsubsection spy + +@DOCSTRING(spy) + +@node symamd, symbfact, spy, Function Reference +@subsubsection symamd + +@DOCSTRING(symamd) + +@node symbfact, symrcm, symamd, Function Reference +@subsubsection symbfact + +@DOCSTRING(symbfact) + +@node symrcm, , symbfact, Function Reference +@subsubsection symrcm + +@DOCSTRING(symrcm) + +@c Local Variables: *** +@c Mode: texinfo *** +@c End: *** diff --git a/libcruft/ChangeLog b/libcruft/ChangeLog --- a/libcruft/ChangeLog +++ b/libcruft/ChangeLog @@ -1,3 +1,29 @@ +2005-02-25 John W. Eaton + + * blas/zher.f: New file. + + Sparse merge. + + 2005-01-13 David Bateman + + * lapack/dgttrf.f lapack/dgttrs.f lapacl/zgttrf.f lapack/zgttrs.f: + new files + + 2005-01-23 David Bateman + + * lapack/dgtsv.f lapack/dpbcon.f lapack/dpbtf2.f lapack/dpbtrf.f + lapack/dpbtrs.f lapack/dptsv.f lapack/dpttrf.f lapack/dpttrs.f + lapack/dptts2.f lapack/zgtsv.f lapack/zpbcon.f lapack/zpbtf2.f + lapack/zpbtrf.f lapack/zpbtrs.f lapack/zptsv.f lapack/zpttrf.f + lapack/zpttrs.f lapck/zptts2.f: New files. + + 2004-12-29 John W. Eaton + + * blas/zbtsv.f: New file. + * lapack/dgbcon.f, lapack/dgbtrf.f, lapack/dgbtrs.f, + lapack/dlatbs.f, lapack/zgbcon.f, lapack/zgbtf2.f, + lapack/zgbtrf.f, lapack/zgbtrs.f, lapack/zlatbs.f: New files. + 2005-02-10 John W. Eaton * misc/cquit.c (octave_signal_caught): New global variable. diff --git a/libcruft/blas/zher.f b/libcruft/blas/zher.f new file mode 100644 --- /dev/null +++ b/libcruft/blas/zher.f @@ -0,0 +1,212 @@ + SUBROUTINE ZHER ( UPLO, N, ALPHA, X, INCX, A, LDA ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA + INTEGER INCX, LDA, N + CHARACTER*1 UPLO +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* ZHER performs the hermitian rank 1 operation +* +* A := alpha*x*conjg( x' ) + A, +* +* where alpha is a real scalar, x is an n element vector and A is an +* n by n hermitian matrix. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array A is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of A +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of A +* is to be referenced. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular part of the hermitian matrix and the strictly +* lower triangular part of A is not referenced. On exit, the +* upper triangular part of the array A is overwritten by the +* upper triangular part of the updated matrix. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular part of the hermitian matrix and the strictly +* upper triangular part of A is not referenced. On exit, the +* lower triangular part of the array A is overwritten by the +* lower triangular part of the updated matrix. +* Note that the imaginary parts of the diagonal elements need +* not be set, they are assumed to be zero, and on exit they +* are set to zero. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JX, KX +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX, DBLE +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO, 'U' ).AND. + $ .NOT.LSAME( UPLO, 'L' ) )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 7 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZHER ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( N.EQ.0 ).OR.( ALPHA.EQ.DBLE( ZERO ) ) ) + $ RETURN +* +* Set the start point in X if the increment is not unity. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the triangular part +* of A. +* + IF( LSAME( UPLO, 'U' ) )THEN +* +* Form A when A is stored in upper triangle. +* + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( X( J ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( X( J ) ) + DO 10, I = 1, J - 1 + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + A( J, J ) = DBLE( A( J, J ) ) + DBLE( X( J )*TEMP ) + ELSE + A( J, J ) = DBLE( A( J, J ) ) + END IF + 20 CONTINUE + ELSE + JX = KX + DO 40, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( X( JX ) ) + IX = KX + DO 30, I = 1, J - 1 + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + A( J, J ) = DBLE( A( J, J ) ) + DBLE( X( JX )*TEMP ) + ELSE + A( J, J ) = DBLE( A( J, J ) ) + END IF + JX = JX + INCX + 40 CONTINUE + END IF + ELSE +* +* Form A when A is stored in lower triangle. +* + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( X( J ) ) + A( J, J ) = DBLE( A( J, J ) ) + DBLE( TEMP*X( J ) ) + DO 50, I = J + 1, N + A( I, J ) = A( I, J ) + X( I )*TEMP + 50 CONTINUE + ELSE + A( J, J ) = DBLE( A( J, J ) ) + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( X( JX ) ) + A( J, J ) = DBLE( A( J, J ) ) + DBLE( TEMP*X( JX ) ) + IX = JX + DO 70, I = J + 1, N + IX = IX + INCX + A( I, J ) = A( I, J ) + X( IX )*TEMP + 70 CONTINUE + ELSE + A( J, J ) = DBLE( A( J, J ) ) + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZHER . +* + END diff --git a/libcruft/blas/ztbsv.f b/libcruft/blas/ztbsv.f new file mode 100644 --- /dev/null +++ b/libcruft/blas/ztbsv.f @@ -0,0 +1,381 @@ + SUBROUTINE ZTBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, K, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* ZTBSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, or conjg( A' )*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular band matrix, with ( k + 1 ) +* diagonals. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' conjg( A' )*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with UPLO = 'U' or 'u', K specifies the number of +* super-diagonals of the matrix A. +* On entry with UPLO = 'L' or 'l', K specifies the number of +* sub-diagonals of the matrix A. +* K must satisfy 0 .le. K. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) +* by n part of the array A must contain the upper triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row +* ( k + 1 ) of the array, the first super-diagonal starting at +* position 2 in row k, and so on. The top left k by k triangle +* of the array A is not referenced. +* The following program segment will transfer an upper +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = K + 1 - J +* DO 10, I = MAX( 1, J - K ), J +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) +* by n part of the array A must contain the lower triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row 1 of +* the array, the first sub-diagonal starting at position 1 in +* row 2, and so on. The bottom right k by k triangle of the +* array A is not referenced. +* The following program segment will transfer a lower +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = 1 - J +* DO 10, I = J, MIN( N, J + K ) +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Note that when DIAG = 'U' or 'u' the elements of the array A +* corresponding to the diagonal elements of the matrix are not +* referenced, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( k + 1 ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JX, KPLUS1, KX, L + LOGICAL NOCONJ, NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( K.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( K + 1 ) )THEN + INFO = 7 + ELSE IF( INCX.EQ.0 )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZTBSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed by sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + L = KPLUS1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( KPLUS1, J ) + TEMP = X( J ) + DO 10, I = J - 1, MAX( 1, J - K ), -1 + X( I ) = X( I ) - TEMP*A( L + I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 40, J = N, 1, -1 + KX = KX - INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = KPLUS1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( KPLUS1, J ) + TEMP = X( JX ) + DO 30, I = J - 1, MAX( 1, J - K ), -1 + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX - INCX + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + L = 1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( 1, J ) + TEMP = X( J ) + DO 50, I = J + 1, MIN( N, J + K ) + X( I ) = X( I ) - TEMP*A( L + I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + KX = KX + INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = 1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( 1, J ) + TEMP = X( JX ) + DO 70, I = J + 1, MIN( N, J + K ) + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX + INCX + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A' )*x or x := inv( conjg( A') )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = X( J ) + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 90, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 100, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( I ) + 100 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( KPLUS1, J ) ) + END IF + X( J ) = TEMP + 110 CONTINUE + ELSE + JX = KX + DO 140, J = 1, N + TEMP = X( JX ) + IX = KX + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 120, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 130, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( KPLUS1, J ) ) + END IF + X( JX ) = TEMP + JX = JX + INCX + IF( J.GT.K ) + $ KX = KX + INCX + 140 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 170, J = N, 1, -1 + TEMP = X( J ) + L = 1 - J + IF( NOCONJ )THEN + DO 150, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( I ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 160, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( I ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( 1, J ) ) + END IF + X( J ) = TEMP + 170 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 200, J = N, 1, -1 + TEMP = X( JX ) + IX = KX + L = 1 - J + IF( NOCONJ )THEN + DO 180, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX - INCX + 180 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 190, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( IX ) + IX = IX - INCX + 190 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( 1, J ) ) + END IF + X( JX ) = TEMP + JX = JX - INCX + IF( ( N - J ).GE.K ) + $ KX = KX - INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTBSV . +* + END diff --git a/libcruft/lapack/dgbcon.f b/libcruft/lapack/dgbcon.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dgbcon.f @@ -0,0 +1,222 @@ + SUBROUTINE DGBCON( NORM, N, KL, KU, AB, LDAB, IPIV, ANORM, RCOND, + $ WORK, IWORK, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER INFO, KL, KU, LDAB, N + DOUBLE PRECISION ANORM, RCOND +* .. +* .. Array Arguments .. + INTEGER IPIV( * ), IWORK( * ) + DOUBLE PRECISION AB( LDAB, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGBCON estimates the reciprocal of the condition number of a real +* general band matrix A, in either the 1-norm or the infinity-norm, +* using the LU factorization computed by DGBTRF. +* +* An estimate is obtained for norm(inv(A)), and the reciprocal of the +* condition number is computed as +* RCOND = 1 / ( norm(A) * norm(inv(A)) ). +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies whether the 1-norm condition number or the +* infinity-norm condition number is required: +* = '1' or 'O': 1-norm; +* = 'I': Infinity-norm. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input) DOUBLE PRECISION array, dimension (LDAB,N) +* Details of the LU factorization of the band matrix A, as +* computed by DGBTRF. U is stored as an upper triangular band +* matrix with KL+KU superdiagonals in rows 1 to KL+KU+1, and +* the multipliers used during the factorization are stored in +* rows KL+KU+2 to 2*KL+KU+1. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= N, row i of the matrix was +* interchanged with row IPIV(i). +* +* ANORM (input) DOUBLE PRECISION +* If NORM = '1' or 'O', the 1-norm of the original matrix A. +* If NORM = 'I', the infinity-norm of the original matrix A. +* +* RCOND (output) DOUBLE PRECISION +* The reciprocal of the condition number of the matrix A, +* computed as RCOND = 1/(norm(A) * norm(inv(A))). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (3*N) +* +* IWORK (workspace) INTEGER array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LNOTI, ONENRM + CHARACTER NORMIN + INTEGER IX, J, JP, KASE, KASE1, KD, LM + DOUBLE PRECISION AINVNM, SCALE, SMLNUM, T +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX + DOUBLE PRECISION DDOT, DLAMCH + EXTERNAL LSAME, IDAMAX, DDOT, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DLACON, DLATBS, DRSCL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' ) + IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.2*KL+KU+1 ) THEN + INFO = -6 + ELSE IF( ANORM.LT.ZERO ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGBCON', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + RCOND = ZERO + IF( N.EQ.0 ) THEN + RCOND = ONE + RETURN + ELSE IF( ANORM.EQ.ZERO ) THEN + RETURN + END IF +* + SMLNUM = DLAMCH( 'Safe minimum' ) +* +* Estimate the norm of inv(A). +* + AINVNM = ZERO + NORMIN = 'N' + IF( ONENRM ) THEN + KASE1 = 1 + ELSE + KASE1 = 2 + END IF + KD = KL + KU + 1 + LNOTI = KL.GT.0 + KASE = 0 + 10 CONTINUE + CALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE ) + IF( KASE.NE.0 ) THEN + IF( KASE.EQ.KASE1 ) THEN +* +* Multiply by inv(L). +* + IF( LNOTI ) THEN + DO 20 J = 1, N - 1 + LM = MIN( KL, N-J ) + JP = IPIV( J ) + T = WORK( JP ) + IF( JP.NE.J ) THEN + WORK( JP ) = WORK( J ) + WORK( J ) = T + END IF + CALL DAXPY( LM, -T, AB( KD+1, J ), 1, WORK( J+1 ), 1 ) + 20 CONTINUE + END IF +* +* Multiply by inv(U). +* + CALL DLATBS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N, + $ KL+KU, AB, LDAB, WORK, SCALE, WORK( 2*N+1 ), + $ INFO ) + ELSE +* +* Multiply by inv(U'). +* + CALL DLATBS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N, + $ KL+KU, AB, LDAB, WORK, SCALE, WORK( 2*N+1 ), + $ INFO ) +* +* Multiply by inv(L'). +* + IF( LNOTI ) THEN + DO 30 J = N - 1, 1, -1 + LM = MIN( KL, N-J ) + WORK( J ) = WORK( J ) - DDOT( LM, AB( KD+1, J ), 1, + $ WORK( J+1 ), 1 ) + JP = IPIV( J ) + IF( JP.NE.J ) THEN + T = WORK( JP ) + WORK( JP ) = WORK( J ) + WORK( J ) = T + END IF + 30 CONTINUE + END IF + END IF +* +* Divide X by 1/SCALE if doing so will not cause overflow. +* + NORMIN = 'Y' + IF( SCALE.NE.ONE ) THEN + IX = IDAMAX( N, WORK, 1 ) + IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO ) + $ GO TO 40 + CALL DRSCL( N, SCALE, WORK, 1 ) + END IF + GO TO 10 + END IF +* +* Compute the estimate of the reciprocal condition number. +* + IF( AINVNM.NE.ZERO ) + $ RCOND = ( ONE / AINVNM ) / ANORM +* + 40 CONTINUE + RETURN +* +* End of DGBCON +* + END diff --git a/libcruft/lapack/dgtsv.f b/libcruft/lapack/dgtsv.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dgtsv.f @@ -0,0 +1,263 @@ + SUBROUTINE DGTSV( N, NRHS, DL, D, DU, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1999 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ) +* .. +* +* Purpose +* ======= +* +* DGTSV solves the equation +* +* A*X = B, +* +* where A is an n by n tridiagonal matrix, by Gaussian elimination with +* partial pivoting. +* +* Note that the equation A'*X = B may be solved by interchanging the +* order of the arguments DU and DL. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* DL (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DL must contain the (n-1) sub-diagonal elements of +* A. +* +* On exit, DL is overwritten by the (n-2) elements of the +* second super-diagonal of the upper triangular matrix U from +* the LU factorization of A, in DL(1), ..., DL(n-2). +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, D must contain the diagonal elements of A. +* +* On exit, D is overwritten by the n diagonal elements of U. +* +* DU (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DU must contain the (n-1) super-diagonal elements +* of A. +* +* On exit, DU is overwritten by the (n-1) elements of the first +* super-diagonal of U. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N by NRHS matrix of right hand side matrix B. +* On exit, if INFO = 0, the N by NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero, and the solution +* has not been computed. The factorization has not been +* completed unless i = N. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J + DOUBLE PRECISION FACT, TEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGTSV ', -INFO ) + RETURN + END IF +* + IF( N.EQ.0 ) + $ RETURN +* + IF( NRHS.EQ.1 ) THEN + DO 10 I = 1, N - 2 + IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN +* +* No row interchange required +* + IF( D( I ).NE.ZERO ) THEN + FACT = DL( I ) / D( I ) + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + B( I+1, 1 ) = B( I+1, 1 ) - FACT*B( I, 1 ) + ELSE + INFO = I + RETURN + END IF + DL( I ) = ZERO + ELSE +* +* Interchange rows I and I+1 +* + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + TEMP = D( I+1 ) + D( I+1 ) = DU( I ) - FACT*TEMP + DL( I ) = DU( I+1 ) + DU( I+1 ) = -FACT*DL( I ) + DU( I ) = TEMP + TEMP = B( I, 1 ) + B( I, 1 ) = B( I+1, 1 ) + B( I+1, 1 ) = TEMP - FACT*B( I+1, 1 ) + END IF + 10 CONTINUE + IF( N.GT.1 ) THEN + I = N - 1 + IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN + IF( D( I ).NE.ZERO ) THEN + FACT = DL( I ) / D( I ) + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + B( I+1, 1 ) = B( I+1, 1 ) - FACT*B( I, 1 ) + ELSE + INFO = I + RETURN + END IF + ELSE + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + TEMP = D( I+1 ) + D( I+1 ) = DU( I ) - FACT*TEMP + DU( I ) = TEMP + TEMP = B( I, 1 ) + B( I, 1 ) = B( I+1, 1 ) + B( I+1, 1 ) = TEMP - FACT*B( I+1, 1 ) + END IF + END IF + IF( D( N ).EQ.ZERO ) THEN + INFO = N + RETURN + END IF + ELSE + DO 40 I = 1, N - 2 + IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN +* +* No row interchange required +* + IF( D( I ).NE.ZERO ) THEN + FACT = DL( I ) / D( I ) + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + DO 20 J = 1, NRHS + B( I+1, J ) = B( I+1, J ) - FACT*B( I, J ) + 20 CONTINUE + ELSE + INFO = I + RETURN + END IF + DL( I ) = ZERO + ELSE +* +* Interchange rows I and I+1 +* + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + TEMP = D( I+1 ) + D( I+1 ) = DU( I ) - FACT*TEMP + DL( I ) = DU( I+1 ) + DU( I+1 ) = -FACT*DL( I ) + DU( I ) = TEMP + DO 30 J = 1, NRHS + TEMP = B( I, J ) + B( I, J ) = B( I+1, J ) + B( I+1, J ) = TEMP - FACT*B( I+1, J ) + 30 CONTINUE + END IF + 40 CONTINUE + IF( N.GT.1 ) THEN + I = N - 1 + IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN + IF( D( I ).NE.ZERO ) THEN + FACT = DL( I ) / D( I ) + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + DO 50 J = 1, NRHS + B( I+1, J ) = B( I+1, J ) - FACT*B( I, J ) + 50 CONTINUE + ELSE + INFO = I + RETURN + END IF + ELSE + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + TEMP = D( I+1 ) + D( I+1 ) = DU( I ) - FACT*TEMP + DU( I ) = TEMP + DO 60 J = 1, NRHS + TEMP = B( I, J ) + B( I, J ) = B( I+1, J ) + B( I+1, J ) = TEMP - FACT*B( I+1, J ) + 60 CONTINUE + END IF + END IF + IF( D( N ).EQ.ZERO ) THEN + INFO = N + RETURN + END IF + END IF +* +* Back solve with the matrix U from the factorization. +* + IF( NRHS.LE.2 ) THEN + J = 1 + 70 CONTINUE + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / D( N-1 ) + DO 80 I = N - 2, 1, -1 + B( I, J ) = ( B( I, J )-DU( I )*B( I+1, J )-DL( I )* + $ B( I+2, J ) ) / D( I ) + 80 CONTINUE + IF( J.LT.NRHS ) THEN + J = J + 1 + GO TO 70 + END IF + ELSE + DO 100 J = 1, NRHS + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / + $ D( N-1 ) + DO 90 I = N - 2, 1, -1 + B( I, J ) = ( B( I, J )-DU( I )*B( I+1, J )-DL( I )* + $ B( I+2, J ) ) / D( I ) + 90 CONTINUE + 100 CONTINUE + END IF +* + RETURN +* +* End of DGTSV +* + END diff --git a/libcruft/lapack/dgttrf.f b/libcruft/lapack/dgttrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dgttrf.f @@ -0,0 +1,149 @@ + SUBROUTINE DGTTRF( N, DL, D, DU, DU2, IPIV, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* DGTTRF computes an LU factorization of a real tridiagonal matrix A +* using elimination with partial pivoting and row interchanges. +* +* The factorization has the form +* A = L * U +* where L is a product of permutation and unit lower bidiagonal +* matrices and U is upper triangular with nonzeros in only the main +* diagonal and first two superdiagonals. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* DL (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DL must contain the (n-1) subdiagonal elements of +* A. +* On exit, DL is overwritten by the (n-1) multipliers that +* define the matrix L from the LU factorization of A. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, D must contain the diagonal elements of A. +* On exit, D is overwritten by the n diagonal elements of the +* upper triangular matrix U from the LU factorization of A. +* +* DU (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DU must contain the (n-1) superdiagonal elements +* of A. +* On exit, DU is overwritten by the (n-1) elements of the first +* superdiagonal of U. +* +* DU2 (output) DOUBLE PRECISION array, dimension (N-2) +* On exit, DU2 is overwritten by the (n-2) elements of the +* second superdiagonal of U. +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION FACT, TEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DGTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Initialize IPIV(i) = i +* + DO 10 I = 1, N + IPIV( I ) = I + 10 CONTINUE +* + DO 20 I = 1, N - 1 + IF( DL( I ).EQ.ZERO ) THEN +* +* Subdiagonal is zero, no elimination is required. +* + IF( D( I ).EQ.ZERO .AND. INFO.EQ.0 ) + $ INFO = I + IF( I.LT.N-1 ) + $ DU2( I ) = ZERO + ELSE IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN +* +* No row interchange required, eliminate DL(I) +* + FACT = DL( I ) / D( I ) + DL( I ) = FACT + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + IF( I.LT.N-1 ) + $ DU2( I ) = ZERO + ELSE +* +* Interchange rows I and I+1, eliminate DL(I) +* + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + DL( I ) = FACT + TEMP = DU( I ) + DU( I ) = D( I+1 ) + D( I+1 ) = TEMP - FACT*D( I+1 ) + IF( I.LT.N-1 ) THEN + DU2( I ) = DU( I+1 ) + DU( I+1 ) = -FACT*DU( I+1 ) + END IF + IPIV( I ) = IPIV( I ) + 1 + END IF + 20 CONTINUE + IF( D( N ).EQ.ZERO .AND. INFO.EQ.0 ) THEN + INFO = N + RETURN + END IF +* + RETURN +* +* End of DGTTRF +* + END diff --git a/libcruft/lapack/dgttrs.f b/libcruft/lapack/dgttrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dgttrs.f @@ -0,0 +1,176 @@ + SUBROUTINE DGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* DGTTRS solves one of the systems of equations +* A*X = B or A'*X = B, +* with a tridiagonal matrix A using the LU factorization computed +* by DGTTRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A'* X = B (Transpose) +* = 'C': A'* X = B (Conjugate transpose = Transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* DL (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) multipliers that define the matrix L from the +* LU factorization of A. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the upper triangular matrix U from +* the LU factorization of A. +* +* DU (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) elements of the first superdiagonal of U. +* +* DU2 (input) DOUBLE PRECISION array, dimension (N-2) +* The (n-2) elements of the second superdiagonal of U. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, B is overwritten by the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL NOTRAN + INTEGER I, J + DOUBLE PRECISION TEMP +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDB.LT.MAX( N, 1 ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( NOTRAN ) THEN +* +* Solve A*X = B using the LU factorization of A, +* overwriting each right hand side vector with its solution. +* + DO 30 J = 1, NRHS +* +* Solve L*x = b. +* + DO 10 I = 1, N - 1 + IF( IPIV( I ).EQ.I ) THEN + B( I+1, J ) = B( I+1, J ) - DL( I )*B( I, J ) + ELSE + TEMP = B( I, J ) + B( I, J ) = B( I+1, J ) + B( I+1, J ) = TEMP - DL( I )*B( I, J ) + END IF + 10 CONTINUE +* +* Solve U*x = b. +* + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / + $ D( N-1 ) + DO 20 I = N - 2, 1, -1 + B( I, J ) = ( B( I, J )-DU( I )*B( I+1, J )-DU2( I )* + $ B( I+2, J ) ) / D( I ) + 20 CONTINUE + 30 CONTINUE + ELSE +* +* Solve A' * X = B. +* + DO 60 J = 1, NRHS +* +* Solve U'*x = b. +* + B( 1, J ) = B( 1, J ) / D( 1 ) + IF( N.GT.1 ) + $ B( 2, J ) = ( B( 2, J )-DU( 1 )*B( 1, J ) ) / D( 2 ) + DO 40 I = 3, N + B( I, J ) = ( B( I, J )-DU( I-1 )*B( I-1, J )-DU2( I-2 )* + $ B( I-2, J ) ) / D( I ) + 40 CONTINUE +* +* Solve L'*x = b. +* + DO 50 I = N - 1, 1, -1 + IF( IPIV( I ).EQ.I ) THEN + B( I, J ) = B( I, J ) - DL( I )*B( I+1, J ) + ELSE + TEMP = B( I+1, J ) + B( I+1, J ) = B( I, J ) - DL( I )*TEMP + B( I, J ) = TEMP + END IF + 50 CONTINUE + 60 CONTINUE + END IF +* +* End of DGTTRS +* + END diff --git a/libcruft/lapack/dlatbs.f b/libcruft/lapack/dlatbs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dlatbs.f @@ -0,0 +1,724 @@ + SUBROUTINE DLATBS( UPLO, TRANS, DIAG, NORMIN, N, KD, AB, LDAB, X, + $ SCALE, CNORM, INFO ) +* +* -- LAPACK auxiliary routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1992 +* +* .. Scalar Arguments .. + CHARACTER DIAG, NORMIN, TRANS, UPLO + INTEGER INFO, KD, LDAB, N + DOUBLE PRECISION SCALE +* .. +* .. Array Arguments .. + DOUBLE PRECISION AB( LDAB, * ), CNORM( * ), X( * ) +* .. +* +* Purpose +* ======= +* +* DLATBS solves one of the triangular systems +* +* A *x = s*b or A'*x = s*b +* +* with scaling to prevent overflow, where A is an upper or lower +* triangular band matrix. Here A' denotes the transpose of A, x and b +* are n-element vectors, and s is a scaling factor, usually less than +* or equal to 1, chosen so that the components of x will be less than +* the overflow threshold. If the unscaled problem will not cause +* overflow, the Level 2 BLAS routine DTBSV is called. If the matrix A +* is singular (A(j,j) = 0 for some j), then s is set to 0 and a +* non-trivial solution to A*x = 0 is returned. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the matrix A is upper or lower triangular. +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* TRANS (input) CHARACTER*1 +* Specifies the operation applied to A. +* = 'N': Solve A * x = s*b (No transpose) +* = 'T': Solve A'* x = s*b (Transpose) +* = 'C': Solve A'* x = s*b (Conjugate transpose = Transpose) +* +* DIAG (input) CHARACTER*1 +* Specifies whether or not the matrix A is unit triangular. +* = 'N': Non-unit triangular +* = 'U': Unit triangular +* +* NORMIN (input) CHARACTER*1 +* Specifies whether CNORM has been set or not. +* = 'Y': CNORM contains the column norms on entry +* = 'N': CNORM is not set on entry. On exit, the norms will +* be computed and stored in CNORM. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of subdiagonals or superdiagonals in the +* triangular matrix A. KD >= 0. +* +* AB (input) DOUBLE PRECISION array, dimension (LDAB,N) +* The upper or lower triangular band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of A is stored +* in the j-th column of the array AB as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* X (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the right hand side b of the triangular system. +* On exit, X is overwritten by the solution vector x. +* +* SCALE (output) DOUBLE PRECISION +* The scaling factor s for the triangular system +* A * x = s*b or A'* x = s*b. +* If SCALE = 0, the matrix A is singular or badly scaled, and +* the vector x is an exact or approximate solution to A*x = 0. +* +* CNORM (input or output) DOUBLE PRECISION array, dimension (N) +* +* If NORMIN = 'Y', CNORM is an input argument and CNORM(j) +* contains the norm of the off-diagonal part of the j-th column +* of A. If TRANS = 'N', CNORM(j) must be greater than or equal +* to the infinity-norm, and if TRANS = 'T' or 'C', CNORM(j) +* must be greater than or equal to the 1-norm. +* +* If NORMIN = 'N', CNORM is an output argument and CNORM(j) +* returns the 1-norm of the offdiagonal part of the j-th column +* of A. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* Further Details +* ======= ======= +* +* A rough bound on x is computed; if that is less than overflow, DTBSV +* is called, otherwise, specific code is used which checks for possible +* overflow or divide-by-zero at every operation. +* +* A columnwise scheme is used for solving A*x = b. The basic algorithm +* if A is lower triangular is +* +* x[1:n] := b[1:n] +* for j = 1, ..., n +* x(j) := x(j) / A(j,j) +* x[j+1:n] := x[j+1:n] - x(j) * A[j+1:n,j] +* end +* +* Define bounds on the components of x after j iterations of the loop: +* M(j) = bound on x[1:j] +* G(j) = bound on x[j+1:n] +* Initially, let M(0) = 0 and G(0) = max{x(i), i=1,...,n}. +* +* Then for iteration j+1 we have +* M(j+1) <= G(j) / | A(j+1,j+1) | +* G(j+1) <= G(j) + M(j+1) * | A[j+2:n,j+1] | +* <= G(j) ( 1 + CNORM(j+1) / | A(j+1,j+1) | ) +* +* where CNORM(j+1) is greater than or equal to the infinity-norm of +* column j+1 of A, not counting the diagonal. Hence +* +* G(j) <= G(0) product ( 1 + CNORM(i) / | A(i,i) | ) +* 1<=i<=j +* and +* +* |x(j)| <= ( G(0) / |A(j,j)| ) product ( 1 + CNORM(i) / |A(i,i)| ) +* 1<=i< j +* +* Since |x(j)| <= M(j), we use the Level 2 BLAS routine DTBSV if the +* reciprocal of the largest M(j), j=1,..,n, is larger than +* max(underflow, 1/overflow). +* +* The bound on x(j) is also used to determine when a step in the +* columnwise method can be performed without fear of overflow. If +* the computed bound is greater than a large constant, x is scaled to +* prevent overflow, but if the bound overflows, x is set to 0, x(j) to +* 1, and scale to 0, and a non-trivial solution to A*x = 0 is found. +* +* Similarly, a row-wise scheme is used to solve A'*x = b. The basic +* algorithm for A upper triangular is +* +* for j = 1, ..., n +* x(j) := ( b(j) - A[1:j-1,j]' * x[1:j-1] ) / A(j,j) +* end +* +* We simultaneously compute two bounds +* G(j) = bound on ( b(i) - A[1:i-1,i]' * x[1:i-1] ), 1<=i<=j +* M(j) = bound on x(i), 1<=i<=j +* +* The initial values are G(0) = 0, M(0) = max{b(i), i=1,..,n}, and we +* add the constraint G(j) >= G(j-1) and M(j) >= M(j-1) for j >= 1. +* Then the bound on x(j) is +* +* M(j) <= M(j-1) * ( 1 + CNORM(j) ) / | A(j,j) | +* +* <= M(0) * product ( ( 1 + CNORM(i) ) / |A(i,i)| ) +* 1<=i<=j +* +* and we can safely call DTBSV if 1/M(n) and 1/G(n) are both greater +* than max(underflow, 1/overflow). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOTRAN, NOUNIT, UPPER + INTEGER I, IMAX, J, JFIRST, JINC, JLAST, JLEN, MAIND + DOUBLE PRECISION BIGNUM, GROW, REC, SMLNUM, SUMJ, TJJ, TJJS, + $ TMAX, TSCAL, USCAL, XBND, XJ, XMAX +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX + DOUBLE PRECISION DASUM, DDOT, DLAMCH + EXTERNAL LSAME, IDAMAX, DASUM, DDOT, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DSCAL, DTBSV, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. Executable Statements .. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOTRAN = LSAME( TRANS, 'N' ) + NOUNIT = LSAME( DIAG, 'N' ) +* +* Test the input parameters. +* + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -2 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -3 + ELSE IF( .NOT.LSAME( NORMIN, 'Y' ) .AND. .NOT. + $ LSAME( NORMIN, 'N' ) ) THEN + INFO = -4 + ELSE IF( N.LT.0 ) THEN + INFO = -5 + ELSE IF( KD.LT.0 ) THEN + INFO = -6 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLATBS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine machine dependent parameters to control overflow. +* + SMLNUM = DLAMCH( 'Safe minimum' ) / DLAMCH( 'Precision' ) + BIGNUM = ONE / SMLNUM + SCALE = ONE +* + IF( LSAME( NORMIN, 'N' ) ) THEN +* +* Compute the 1-norm of each column, not including the diagonal. +* + IF( UPPER ) THEN +* +* A is upper triangular. +* + DO 10 J = 1, N + JLEN = MIN( KD, J-1 ) + CNORM( J ) = DASUM( JLEN, AB( KD+1-JLEN, J ), 1 ) + 10 CONTINUE + ELSE +* +* A is lower triangular. +* + DO 20 J = 1, N + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.0 ) THEN + CNORM( J ) = DASUM( JLEN, AB( 2, J ), 1 ) + ELSE + CNORM( J ) = ZERO + END IF + 20 CONTINUE + END IF + END IF +* +* Scale the column norms by TSCAL if the maximum element in CNORM is +* greater than BIGNUM. +* + IMAX = IDAMAX( N, CNORM, 1 ) + TMAX = CNORM( IMAX ) + IF( TMAX.LE.BIGNUM ) THEN + TSCAL = ONE + ELSE + TSCAL = ONE / ( SMLNUM*TMAX ) + CALL DSCAL( N, TSCAL, CNORM, 1 ) + END IF +* +* Compute a bound on the computed solution vector to see if the +* Level 2 BLAS routine DTBSV can be used. +* + J = IDAMAX( N, X, 1 ) + XMAX = ABS( X( J ) ) + XBND = XMAX + IF( NOTRAN ) THEN +* +* Compute the growth in A * x = b. +* + IF( UPPER ) THEN + JFIRST = N + JLAST = 1 + JINC = -1 + MAIND = KD + 1 + ELSE + JFIRST = 1 + JLAST = N + JINC = 1 + MAIND = 1 + END IF +* + IF( TSCAL.NE.ONE ) THEN + GROW = ZERO + GO TO 50 + END IF +* + IF( NOUNIT ) THEN +* +* A is non-unit triangular. +* +* Compute GROW = 1/G(j) and XBND = 1/M(j). +* Initially, G(0) = max{x(i), i=1,...,n}. +* + GROW = ONE / MAX( XBND, SMLNUM ) + XBND = GROW + DO 30 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 50 +* +* M(j) = G(j-1) / abs(A(j,j)) +* + TJJ = ABS( AB( MAIND, J ) ) + XBND = MIN( XBND, MIN( ONE, TJJ )*GROW ) + IF( TJJ+CNORM( J ).GE.SMLNUM ) THEN +* +* G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) ) +* + GROW = GROW*( TJJ / ( TJJ+CNORM( J ) ) ) + ELSE +* +* G(j) could overflow, set GROW to 0. +* + GROW = ZERO + END IF + 30 CONTINUE + GROW = XBND + ELSE +* +* A is unit triangular. +* +* Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. +* + GROW = MIN( ONE, ONE / MAX( XBND, SMLNUM ) ) + DO 40 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 50 +* +* G(j) = G(j-1)*( 1 + CNORM(j) ) +* + GROW = GROW*( ONE / ( ONE+CNORM( J ) ) ) + 40 CONTINUE + END IF + 50 CONTINUE +* + ELSE +* +* Compute the growth in A' * x = b. +* + IF( UPPER ) THEN + JFIRST = 1 + JLAST = N + JINC = 1 + MAIND = KD + 1 + ELSE + JFIRST = N + JLAST = 1 + JINC = -1 + MAIND = 1 + END IF +* + IF( TSCAL.NE.ONE ) THEN + GROW = ZERO + GO TO 80 + END IF +* + IF( NOUNIT ) THEN +* +* A is non-unit triangular. +* +* Compute GROW = 1/G(j) and XBND = 1/M(j). +* Initially, M(0) = max{x(i), i=1,...,n}. +* + GROW = ONE / MAX( XBND, SMLNUM ) + XBND = GROW + DO 60 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 80 +* +* G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) ) +* + XJ = ONE + CNORM( J ) + GROW = MIN( GROW, XBND / XJ ) +* +* M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j)) +* + TJJ = ABS( AB( MAIND, J ) ) + IF( XJ.GT.TJJ ) + $ XBND = XBND*( TJJ / XJ ) + 60 CONTINUE + GROW = MIN( GROW, XBND ) + ELSE +* +* A is unit triangular. +* +* Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. +* + GROW = MIN( ONE, ONE / MAX( XBND, SMLNUM ) ) + DO 70 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 80 +* +* G(j) = ( 1 + CNORM(j) )*G(j-1) +* + XJ = ONE + CNORM( J ) + GROW = GROW / XJ + 70 CONTINUE + END IF + 80 CONTINUE + END IF +* + IF( ( GROW*TSCAL ).GT.SMLNUM ) THEN +* +* Use the Level 2 BLAS solve if the reciprocal of the bound on +* elements of X is not too small. +* + CALL DTBSV( UPLO, TRANS, DIAG, N, KD, AB, LDAB, X, 1 ) + ELSE +* +* Use a Level 1 BLAS solve, scaling intermediate results. +* + IF( XMAX.GT.BIGNUM ) THEN +* +* Scale X so that its components are less than or equal to +* BIGNUM in absolute value. +* + SCALE = BIGNUM / XMAX + CALL DSCAL( N, SCALE, X, 1 ) + XMAX = BIGNUM + END IF +* + IF( NOTRAN ) THEN +* +* Solve A * x = b +* + DO 110 J = JFIRST, JLAST, JINC +* +* Compute x(j) = b(j) / A(j,j), scaling x if necessary. +* + XJ = ABS( X( J ) ) + IF( NOUNIT ) THEN + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + IF( TSCAL.EQ.ONE ) + $ GO TO 100 + END IF + TJJ = ABS( TJJS ) + IF( TJJ.GT.SMLNUM ) THEN +* +* abs(A(j,j)) > SMLNUM: +* + IF( TJJ.LT.ONE ) THEN + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by 1/b(j). +* + REC = ONE / XJ + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF + X( J ) = X( J ) / TJJS + XJ = ABS( X( J ) ) + ELSE IF( TJJ.GT.ZERO ) THEN +* +* 0 < abs(A(j,j)) <= SMLNUM: +* + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM +* to avoid overflow when dividing by A(j,j). +* + REC = ( TJJ*BIGNUM ) / XJ + IF( CNORM( J ).GT.ONE ) THEN +* +* Scale by 1/CNORM(j) to avoid overflow when +* multiplying x(j) times column j. +* + REC = REC / CNORM( J ) + END IF + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + X( J ) = X( J ) / TJJS + XJ = ABS( X( J ) ) + ELSE +* +* A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and +* scale = 0, and compute a solution to A*x = 0. +* + DO 90 I = 1, N + X( I ) = ZERO + 90 CONTINUE + X( J ) = ONE + XJ = ONE + SCALE = ZERO + XMAX = ZERO + END IF + 100 CONTINUE +* +* Scale x if necessary to avoid overflow when adding a +* multiple of column j of A. +* + IF( XJ.GT.ONE ) THEN + REC = ONE / XJ + IF( CNORM( J ).GT.( BIGNUM-XMAX )*REC ) THEN +* +* Scale x by 1/(2*abs(x(j))). +* + REC = REC*HALF + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + END IF + ELSE IF( XJ*CNORM( J ).GT.( BIGNUM-XMAX ) ) THEN +* +* Scale x by 1/2. +* + CALL DSCAL( N, HALF, X, 1 ) + SCALE = SCALE*HALF + END IF +* + IF( UPPER ) THEN + IF( J.GT.1 ) THEN +* +* Compute the update +* x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - +* x(j)* A(max(1,j-kd):j-1,j) +* + JLEN = MIN( KD, J-1 ) + CALL DAXPY( JLEN, -X( J )*TSCAL, + $ AB( KD+1-JLEN, J ), 1, X( J-JLEN ), 1 ) + I = IDAMAX( J-1, X, 1 ) + XMAX = ABS( X( I ) ) + END IF + ELSE IF( J.LT.N ) THEN +* +* Compute the update +* x(j+1:min(j+kd,n)) := x(j+1:min(j+kd,n)) - +* x(j) * A(j+1:min(j+kd,n),j) +* + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.0 ) + $ CALL DAXPY( JLEN, -X( J )*TSCAL, AB( 2, J ), 1, + $ X( J+1 ), 1 ) + I = J + IDAMAX( N-J, X( J+1 ), 1 ) + XMAX = ABS( X( I ) ) + END IF + 110 CONTINUE +* + ELSE +* +* Solve A' * x = b +* + DO 160 J = JFIRST, JLAST, JINC +* +* Compute x(j) = b(j) - sum A(k,j)*x(k). +* k<>j +* + XJ = ABS( X( J ) ) + USCAL = TSCAL + REC = ONE / MAX( XMAX, ONE ) + IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN +* +* If x(j) could overflow, scale x by 1/(2*XMAX). +* + REC = REC*HALF + IF( NOUNIT ) THEN + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + END IF + TJJ = ABS( TJJS ) + IF( TJJ.GT.ONE ) THEN +* +* Divide by A(j,j) when scaling x if A(j,j) > 1. +* + REC = MIN( ONE, REC*TJJ ) + USCAL = USCAL / TJJS + END IF + IF( REC.LT.ONE ) THEN + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF +* + SUMJ = ZERO + IF( USCAL.EQ.ONE ) THEN +* +* If the scaling needed for A in the dot product is 1, +* call DDOT to perform the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + SUMJ = DDOT( JLEN, AB( KD+1-JLEN, J ), 1, + $ X( J-JLEN ), 1 ) + ELSE + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.0 ) + $ SUMJ = DDOT( JLEN, AB( 2, J ), 1, X( J+1 ), 1 ) + END IF + ELSE +* +* Otherwise, use in-line code for the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + DO 120 I = 1, JLEN + SUMJ = SUMJ + ( AB( KD+I-JLEN, J )*USCAL )* + $ X( J-JLEN-1+I ) + 120 CONTINUE + ELSE + JLEN = MIN( KD, N-J ) + DO 130 I = 1, JLEN + SUMJ = SUMJ + ( AB( I+1, J )*USCAL )*X( J+I ) + 130 CONTINUE + END IF + END IF +* + IF( USCAL.EQ.TSCAL ) THEN +* +* Compute x(j) := ( x(j) - sumj ) / A(j,j) if 1/A(j,j) +* was not used to scale the dotproduct. +* + X( J ) = X( J ) - SUMJ + XJ = ABS( X( J ) ) + IF( NOUNIT ) THEN +* +* Compute x(j) = x(j) / A(j,j), scaling if necessary. +* + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + IF( TSCAL.EQ.ONE ) + $ GO TO 150 + END IF + TJJ = ABS( TJJS ) + IF( TJJ.GT.SMLNUM ) THEN +* +* abs(A(j,j)) > SMLNUM: +* + IF( TJJ.LT.ONE ) THEN + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale X by 1/abs(x(j)). +* + REC = ONE / XJ + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF + X( J ) = X( J ) / TJJS + ELSE IF( TJJ.GT.ZERO ) THEN +* +* 0 < abs(A(j,j)) <= SMLNUM: +* + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. +* + REC = ( TJJ*BIGNUM ) / XJ + CALL DSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + X( J ) = X( J ) / TJJS + ELSE +* +* A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and +* scale = 0, and compute a solution to A'*x = 0. +* + DO 140 I = 1, N + X( I ) = ZERO + 140 CONTINUE + X( J ) = ONE + SCALE = ZERO + XMAX = ZERO + END IF + 150 CONTINUE + ELSE +* +* Compute x(j) := x(j) / A(j,j) - sumj if the dot +* product has already been divided by 1/A(j,j). +* + X( J ) = X( J ) / TJJS - SUMJ + END IF + XMAX = MAX( XMAX, ABS( X( J ) ) ) + 160 CONTINUE + END IF + SCALE = SCALE / TSCAL + END IF +* +* Scale the column norms by 1/TSCAL for return. +* + IF( TSCAL.NE.ONE ) THEN + CALL DSCAL( N, ONE / TSCAL, CNORM, 1 ) + END IF +* + RETURN +* +* End of DLATBS +* + END diff --git a/libcruft/lapack/dpbcon.f b/libcruft/lapack/dpbcon.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpbcon.f @@ -0,0 +1,188 @@ + SUBROUTINE DPBCON( UPLO, N, KD, AB, LDAB, ANORM, RCOND, WORK, + $ IWORK, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N + DOUBLE PRECISION ANORM, RCOND +* .. +* .. Array Arguments .. + INTEGER IWORK( * ) + DOUBLE PRECISION AB( LDAB, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DPBCON estimates the reciprocal of the condition number (in the +* 1-norm) of a real symmetric positive definite band matrix using the +* Cholesky factorization A = U**T*U or A = L*L**T computed by DPBTRF. +* +* An estimate is obtained for norm(inv(A)), and the reciprocal of the +* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangular factor stored in AB; +* = 'L': Lower triangular factor stored in AB. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of subdiagonals if UPLO = 'L'. KD >= 0. +* +* AB (input) DOUBLE PRECISION array, dimension (LDAB,N) +* The triangular factor U or L from the Cholesky factorization +* A = U**T*U or A = L*L**T of the band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of U or L is +* stored in the j-th column of the array AB as follows: +* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j; +* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* ANORM (input) DOUBLE PRECISION +* The 1-norm (or infinity-norm) of the symmetric band matrix A. +* +* RCOND (output) DOUBLE PRECISION +* The reciprocal of the condition number of the matrix A, +* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an +* estimate of the 1-norm of inv(A) computed in this routine. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (3*N) +* +* IWORK (workspace) INTEGER array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + CHARACTER NORMIN + INTEGER IX, KASE + DOUBLE PRECISION AINVNM, SCALE, SCALEL, SCALEU, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, IDAMAX, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DLACON, DLATBS, DRSCL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + ELSE IF( ANORM.LT.ZERO ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPBCON', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + RCOND = ZERO + IF( N.EQ.0 ) THEN + RCOND = ONE + RETURN + ELSE IF( ANORM.EQ.ZERO ) THEN + RETURN + END IF +* + SMLNUM = DLAMCH( 'Safe minimum' ) +* +* Estimate the 1-norm of the inverse. +* + KASE = 0 + NORMIN = 'N' + 10 CONTINUE + CALL DLACON( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE ) + IF( KASE.NE.0 ) THEN + IF( UPPER ) THEN +* +* Multiply by inv(U'). +* + CALL DLATBS( 'Upper', 'Transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEL, WORK( 2*N+1 ), + $ INFO ) + NORMIN = 'Y' +* +* Multiply by inv(U). +* + CALL DLATBS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEU, WORK( 2*N+1 ), + $ INFO ) + ELSE +* +* Multiply by inv(L). +* + CALL DLATBS( 'Lower', 'No transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEL, WORK( 2*N+1 ), + $ INFO ) + NORMIN = 'Y' +* +* Multiply by inv(L'). +* + CALL DLATBS( 'Lower', 'Transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEU, WORK( 2*N+1 ), + $ INFO ) + END IF +* +* Multiply by 1/SCALE if doing so will not cause overflow. +* + SCALE = SCALEL*SCALEU + IF( SCALE.NE.ONE ) THEN + IX = IDAMAX( N, WORK, 1 ) + IF( SCALE.LT.ABS( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO ) + $ GO TO 20 + CALL DRSCL( N, SCALE, WORK, 1 ) + END IF + GO TO 10 + END IF +* +* Compute the estimate of the reciprocal condition number. +* + IF( AINVNM.NE.ZERO ) + $ RCOND = ( ONE / AINVNM ) / ANORM +* + 20 CONTINUE +* + RETURN +* +* End of DPBCON +* + END diff --git a/libcruft/lapack/dpbtf2.f b/libcruft/lapack/dpbtf2.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpbtf2.f @@ -0,0 +1,195 @@ + SUBROUTINE DPBTF2( UPLO, N, KD, AB, LDAB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* DPBTF2 computes the Cholesky factorization of a real symmetric +* positive definite band matrix A. +* +* The factorization has the form +* A = U' * U , if UPLO = 'U', or +* A = L * L', if UPLO = 'L', +* where U is an upper triangular matrix, U' is the transpose of U, and +* L is lower triangular. +* +* This is the unblocked version of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* symmetric matrix A is stored: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of super-diagonals of the matrix A if UPLO = 'U', +* or the number of sub-diagonals if UPLO = 'L'. KD >= 0. +* +* AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) +* On entry, the upper or lower triangle of the symmetric band +* matrix A, stored in the first KD+1 rows of the array. The +* j-th column of A is stored in the j-th column of the array AB +* as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* On exit, if INFO = 0, the triangular factor U or L from the +* Cholesky factorization A = U'*U or A = L*L' of the band +* matrix A, in the same storage format as A. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, the leading minor of order k is not +* positive definite, and the factorization could not be +* completed. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* N = 6, KD = 2, and UPLO = 'U': +* +* On entry: On exit: +* +* * * a13 a24 a35 a46 * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* +* Similarly, if UPLO = 'L' the format of A is as follows: +* +* On entry: On exit: +* +* a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66 +* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 * +* a31 a42 a53 a64 * * l31 l42 l53 l64 * * +* +* Array elements marked * are not used by the routine. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J, KLD, KN + DOUBLE PRECISION AJJ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, DSYR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPBTF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + KLD = MAX( 1, LDAB-1 ) +* + IF( UPPER ) THEN +* +* Compute the Cholesky factorization A = U'*U. +* + DO 10 J = 1, N +* +* Compute U(J,J) and test for non-positive-definiteness. +* + AJJ = AB( KD+1, J ) + IF( AJJ.LE.ZERO ) + $ GO TO 30 + AJJ = SQRT( AJJ ) + AB( KD+1, J ) = AJJ +* +* Compute elements J+1:J+KN of row J and update the +* trailing submatrix within the band. +* + KN = MIN( KD, N-J ) + IF( KN.GT.0 ) THEN + CALL DSCAL( KN, ONE / AJJ, AB( KD, J+1 ), KLD ) + CALL DSYR( 'Upper', KN, -ONE, AB( KD, J+1 ), KLD, + $ AB( KD+1, J+1 ), KLD ) + END IF + 10 CONTINUE + ELSE +* +* Compute the Cholesky factorization A = L*L'. +* + DO 20 J = 1, N +* +* Compute L(J,J) and test for non-positive-definiteness. +* + AJJ = AB( 1, J ) + IF( AJJ.LE.ZERO ) + $ GO TO 30 + AJJ = SQRT( AJJ ) + AB( 1, J ) = AJJ +* +* Compute elements J+1:J+KN of column J and update the +* trailing submatrix within the band. +* + KN = MIN( KD, N-J ) + IF( KN.GT.0 ) THEN + CALL DSCAL( KN, ONE / AJJ, AB( 2, J ), 1 ) + CALL DSYR( 'Lower', KN, -ONE, AB( 2, J ), 1, + $ AB( 1, J+1 ), KLD ) + END IF + 20 CONTINUE + END IF + RETURN +* + 30 CONTINUE + INFO = J + RETURN +* +* End of DPBTF2 +* + END diff --git a/libcruft/lapack/dpbtrf.f b/libcruft/lapack/dpbtrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpbtrf.f @@ -0,0 +1,365 @@ + SUBROUTINE DPBTRF( UPLO, N, KD, AB, LDAB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* DPBTRF computes the Cholesky factorization of a real symmetric +* positive definite band matrix A. +* +* The factorization has the form +* A = U**T * U, if UPLO = 'U', or +* A = L * L**T, if UPLO = 'L', +* where U is an upper triangular matrix and L is lower triangular. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of subdiagonals if UPLO = 'L'. KD >= 0. +* +* AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) +* On entry, the upper or lower triangle of the symmetric band +* matrix A, stored in the first KD+1 rows of the array. The +* j-th column of A is stored in the j-th column of the array AB +* as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* On exit, if INFO = 0, the triangular factor U or L from the +* Cholesky factorization A = U**T*U or A = L*L**T of the band +* matrix A, in the same storage format as A. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite, and the factorization could not be +* completed. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* N = 6, KD = 2, and UPLO = 'U': +* +* On entry: On exit: +* +* * * a13 a24 a35 a46 * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* +* Similarly, if UPLO = 'L' the format of A is as follows: +* +* On entry: On exit: +* +* a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66 +* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 * +* a31 a42 a53 a64 * * l31 l42 l53 l64 * * +* +* Array elements marked * are not used by the routine. +* +* Contributed by +* Peter Mayes and Giuseppe Radicati, IBM ECSEC, Rome, March 23, 1989 +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) + INTEGER NBMAX, LDWORK + PARAMETER ( NBMAX = 32, LDWORK = NBMAX+1 ) +* .. +* .. Local Scalars .. + INTEGER I, I2, I3, IB, II, J, JJ, NB +* .. +* .. Local Arrays .. + DOUBLE PRECISION WORK( LDWORK, NBMAX ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DPBTF2, DPOTF2, DSYRK, DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.LSAME( UPLO, 'U' ) ) .AND. + $ ( .NOT.LSAME( UPLO, 'L' ) ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPBTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment +* + NB = ILAENV( 1, 'DPBTRF', UPLO, N, KD, -1, -1 ) +* +* The block size must not exceed the semi-bandwidth KD, and must not +* exceed the limit set by the size of the local array WORK. +* + NB = MIN( NB, NBMAX ) +* + IF( NB.LE.1 .OR. NB.GT.KD ) THEN +* +* Use unblocked code +* + CALL DPBTF2( UPLO, N, KD, AB, LDAB, INFO ) + ELSE +* +* Use blocked code +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Compute the Cholesky factorization of a symmetric band +* matrix, given the upper triangle of the matrix in band +* storage. +* +* Zero the upper triangle of the work array. +* + DO 20 J = 1, NB + DO 10 I = 1, J - 1 + WORK( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* Process the band matrix one diagonal block at a time. +* + DO 70 I = 1, N, NB + IB = MIN( NB, N-I+1 ) +* +* Factorize the diagonal block +* + CALL DPOTF2( UPLO, IB, AB( KD+1, I ), LDAB-1, II ) + IF( II.NE.0 ) THEN + INFO = I + II - 1 + GO TO 150 + END IF + IF( I+IB.LE.N ) THEN +* +* Update the relevant part of the trailing submatrix. +* If A11 denotes the diagonal block which has just been +* factorized, then we need to update the remaining +* blocks in the diagram: +* +* A11 A12 A13 +* A22 A23 +* A33 +* +* The numbers of rows and columns in the partitioning +* are IB, I2, I3 respectively. The blocks A12, A22 and +* A23 are empty if IB = KD. The upper triangle of A13 +* lies outside the band. +* + I2 = MIN( KD-IB, N-I-IB+1 ) + I3 = MIN( IB, N-I-KD+1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A12 +* + CALL DTRSM( 'Left', 'Upper', 'Transpose', + $ 'Non-unit', IB, I2, ONE, AB( KD+1, I ), + $ LDAB-1, AB( KD+1-IB, I+IB ), LDAB-1 ) +* +* Update A22 +* + CALL DSYRK( 'Upper', 'Transpose', I2, IB, -ONE, + $ AB( KD+1-IB, I+IB ), LDAB-1, ONE, + $ AB( KD+1, I+IB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Copy the lower triangle of A13 into the work array. +* + DO 40 JJ = 1, I3 + DO 30 II = JJ, IB + WORK( II, JJ ) = AB( II-JJ+1, JJ+I+KD-1 ) + 30 CONTINUE + 40 CONTINUE +* +* Update A13 (in the work array). +* + CALL DTRSM( 'Left', 'Upper', 'Transpose', + $ 'Non-unit', IB, I3, ONE, AB( KD+1, I ), + $ LDAB-1, WORK, LDWORK ) +* +* Update A23 +* + IF( I2.GT.0 ) + $ CALL DGEMM( 'Transpose', 'No Transpose', I2, I3, + $ IB, -ONE, AB( KD+1-IB, I+IB ), + $ LDAB-1, WORK, LDWORK, ONE, + $ AB( 1+IB, I+KD ), LDAB-1 ) +* +* Update A33 +* + CALL DSYRK( 'Upper', 'Transpose', I3, IB, -ONE, + $ WORK, LDWORK, ONE, AB( KD+1, I+KD ), + $ LDAB-1 ) +* +* Copy the lower triangle of A13 back into place. +* + DO 60 JJ = 1, I3 + DO 50 II = JJ, IB + AB( II-JJ+1, JJ+I+KD-1 ) = WORK( II, JJ ) + 50 CONTINUE + 60 CONTINUE + END IF + END IF + 70 CONTINUE + ELSE +* +* Compute the Cholesky factorization of a symmetric band +* matrix, given the lower triangle of the matrix in band +* storage. +* +* Zero the lower triangle of the work array. +* + DO 90 J = 1, NB + DO 80 I = J + 1, NB + WORK( I, J ) = ZERO + 80 CONTINUE + 90 CONTINUE +* +* Process the band matrix one diagonal block at a time. +* + DO 140 I = 1, N, NB + IB = MIN( NB, N-I+1 ) +* +* Factorize the diagonal block +* + CALL DPOTF2( UPLO, IB, AB( 1, I ), LDAB-1, II ) + IF( II.NE.0 ) THEN + INFO = I + II - 1 + GO TO 150 + END IF + IF( I+IB.LE.N ) THEN +* +* Update the relevant part of the trailing submatrix. +* If A11 denotes the diagonal block which has just been +* factorized, then we need to update the remaining +* blocks in the diagram: +* +* A11 +* A21 A22 +* A31 A32 A33 +* +* The numbers of rows and columns in the partitioning +* are IB, I2, I3 respectively. The blocks A21, A22 and +* A32 are empty if IB = KD. The lower triangle of A31 +* lies outside the band. +* + I2 = MIN( KD-IB, N-I-IB+1 ) + I3 = MIN( IB, N-I-KD+1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A21 +* + CALL DTRSM( 'Right', 'Lower', 'Transpose', + $ 'Non-unit', I2, IB, ONE, AB( 1, I ), + $ LDAB-1, AB( 1+IB, I ), LDAB-1 ) +* +* Update A22 +* + CALL DSYRK( 'Lower', 'No Transpose', I2, IB, -ONE, + $ AB( 1+IB, I ), LDAB-1, ONE, + $ AB( 1, I+IB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Copy the upper triangle of A31 into the work array. +* + DO 110 JJ = 1, IB + DO 100 II = 1, MIN( JJ, I3 ) + WORK( II, JJ ) = AB( KD+1-JJ+II, JJ+I-1 ) + 100 CONTINUE + 110 CONTINUE +* +* Update A31 (in the work array). +* + CALL DTRSM( 'Right', 'Lower', 'Transpose', + $ 'Non-unit', I3, IB, ONE, AB( 1, I ), + $ LDAB-1, WORK, LDWORK ) +* +* Update A32 +* + IF( I2.GT.0 ) + $ CALL DGEMM( 'No transpose', 'Transpose', I3, I2, + $ IB, -ONE, WORK, LDWORK, + $ AB( 1+IB, I ), LDAB-1, ONE, + $ AB( 1+KD-IB, I+IB ), LDAB-1 ) +* +* Update A33 +* + CALL DSYRK( 'Lower', 'No Transpose', I3, IB, -ONE, + $ WORK, LDWORK, ONE, AB( 1, I+KD ), + $ LDAB-1 ) +* +* Copy the upper triangle of A31 back into place. +* + DO 130 JJ = 1, IB + DO 120 II = 1, MIN( JJ, I3 ) + AB( KD+1-JJ+II, JJ+I-1 ) = WORK( II, JJ ) + 120 CONTINUE + 130 CONTINUE + END IF + END IF + 140 CONTINUE + END IF + END IF + RETURN +* + 150 CONTINUE + RETURN +* +* End of DPBTRF +* + END diff --git a/libcruft/lapack/dpbtrs.f b/libcruft/lapack/dpbtrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpbtrs.f @@ -0,0 +1,146 @@ + SUBROUTINE DPBTRS( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DPBTRS solves a system of linear equations A*X = B with a symmetric +* positive definite band matrix A using the Cholesky factorization +* A = U**T*U or A = L*L**T computed by DPBTRF. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangular factor stored in AB; +* = 'L': Lower triangular factor stored in AB. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of subdiagonals if UPLO = 'L'. KD >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* AB (input) DOUBLE PRECISION array, dimension (LDAB,N) +* The triangular factor U or L from the Cholesky factorization +* A = U**T*U or A = L*L**T of the band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of U or L is +* stored in the j-th column of the array AB as follows: +* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j; +* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DTBSV, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -6 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPBTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Solve A*X = B where A = U'*U. +* + DO 10 J = 1, NRHS +* +* Solve U'*X = B, overwriting B with X. +* + CALL DTBSV( 'Upper', 'Transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) +* +* Solve U*X = B, overwriting B with X. +* + CALL DTBSV( 'Upper', 'No transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) + 10 CONTINUE + ELSE +* +* Solve A*X = B where A = L*L'. +* + DO 20 J = 1, NRHS +* +* Solve L*X = B, overwriting B with X. +* + CALL DTBSV( 'Lower', 'No transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) +* +* Solve L'*X = B, overwriting B with X. +* + CALL DTBSV( 'Lower', 'Transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) + 20 CONTINUE + END IF +* + RETURN +* +* End of DPBTRS +* + END diff --git a/libcruft/lapack/dptsv.f b/libcruft/lapack/dptsv.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dptsv.f @@ -0,0 +1,100 @@ + SUBROUTINE DPTSV( N, NRHS, D, E, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 25, 1997 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTSV computes the solution to a real system of linear equations +* A*X = B, where A is an N-by-N symmetric positive definite tridiagonal +* matrix, and X and B are N-by-NRHS matrices. +* +* A is factored as A = L*D*L**T, and the factored form of A is then +* used to solve the system of equations. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. On exit, the n diagonal elements of the diagonal matrix +* D from the factorization A = L*D*L**T. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix A. On exit, the (n-1) subdiagonal elements of the +* unit bidiagonal factor L from the L*D*L**T factorization of +* A. (E can also be regarded as the superdiagonal of the unit +* bidiagonal factor U from the U**T*D*U factorization of A.) +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N-by-NRHS right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite, and the solution has not been +* computed. The factorization has not been completed +* unless i = N. +* +* ===================================================================== +* +* .. External Subroutines .. + EXTERNAL DPTTRF, DPTTRS, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPTSV ', -INFO ) + RETURN + END IF +* +* Compute the L*D*L' (or U'*D*U) factorization of A. +* + CALL DPTTRF( N, D, E, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL DPTTRS( N, NRHS, D, E, B, LDB, INFO ) + END IF + RETURN +* +* End of DPTSV +* + END diff --git a/libcruft/lapack/dpttrf.f b/libcruft/lapack/dpttrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpttrf.f @@ -0,0 +1,153 @@ + SUBROUTINE DPTTRF( N, D, E, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTTRF computes the L*D*L' factorization of a real symmetric +* positive definite tridiagonal matrix A. The factorization may also +* be regarded as having the form A = U'*D*U. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. On exit, the n diagonal elements of the diagonal matrix +* D from the L*D*L' factorization of A. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix A. On exit, the (n-1) subdiagonal elements of the +* unit bidiagonal factor L from the L*D*L' factorization of A. +* E can also be regarded as the superdiagonal of the unit +* bidiagonal factor U from the U'*D*U factorization of A. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, the leading minor of order k is not +* positive definite; if k < N, the factorization could not +* be completed, while if k = N, the factorization was +* completed, but D(N) = 0. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, I4 + DOUBLE PRECISION EI +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DPTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Compute the L*D*L' (or U'*D*U) factorization of A. +* + I4 = MOD( N-1, 4 ) + DO 10 I = 1, I4 + IF( D( I ).LE.ZERO ) THEN + INFO = I + GO TO 30 + END IF + EI = E( I ) + E( I ) = EI / D( I ) + D( I+1 ) = D( I+1 ) - E( I )*EI + 10 CONTINUE +* + DO 20 I = I4 + 1, N - 4, 4 +* +* Drop out of the loop if d(i) <= 0: the matrix is not positive +* definite. +* + IF( D( I ).LE.ZERO ) THEN + INFO = I + GO TO 30 + END IF +* +* Solve for e(i) and d(i+1). +* + EI = E( I ) + E( I ) = EI / D( I ) + D( I+1 ) = D( I+1 ) - E( I )*EI +* + IF( D( I+1 ).LE.ZERO ) THEN + INFO = I + 1 + GO TO 30 + END IF +* +* Solve for e(i+1) and d(i+2). +* + EI = E( I+1 ) + E( I+1 ) = EI / D( I+1 ) + D( I+2 ) = D( I+2 ) - E( I+1 )*EI +* + IF( D( I+2 ).LE.ZERO ) THEN + INFO = I + 2 + GO TO 30 + END IF +* +* Solve for e(i+2) and d(i+3). +* + EI = E( I+2 ) + E( I+2 ) = EI / D( I+2 ) + D( I+3 ) = D( I+3 ) - E( I+2 )*EI +* + IF( D( I+3 ).LE.ZERO ) THEN + INFO = I + 3 + GO TO 30 + END IF +* +* Solve for e(i+3) and d(i+4). +* + EI = E( I+3 ) + E( I+3 ) = EI / D( I+3 ) + D( I+4 ) = D( I+4 ) - E( I+3 )*EI + 20 CONTINUE +* +* Check d(n) for positive definiteness. +* + IF( D( N ).LE.ZERO ) + $ INFO = N +* + 30 CONTINUE + RETURN +* +* End of DPTTRF +* + END diff --git a/libcruft/lapack/dpttrs.f b/libcruft/lapack/dpttrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dpttrs.f @@ -0,0 +1,115 @@ + SUBROUTINE DPTTRS( N, NRHS, D, E, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTTRS solves a tridiagonal system of the form +* A * X = B +* using the L*D*L' factorization of A computed by DPTTRF. D is a +* diagonal matrix specified in the vector D, L is a unit bidiagonal +* matrix whose subdiagonal is specified in the vector E, and X and B +* are N by NRHS matrices. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the tridiagonal matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the diagonal matrix D from the +* L*D*L' factorization of A. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) subdiagonal elements of the unit bidiagonal factor +* L from the L*D*L' factorization of A. E can also be regarded +* as the superdiagonal of the unit bidiagonal factor U from the +* factorization A = U'*D*U. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side vectors B for the system of +* linear equations. +* On exit, the solution vectors, X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER J, JB, NB +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DPTTS2, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* +* Determine the number of right-hand sides to solve at a time. +* + IF( NRHS.EQ.1 ) THEN + NB = 1 + ELSE + NB = MAX( 1, ILAENV( 1, 'DPTTRS', ' ', N, NRHS, -1, -1 ) ) + END IF +* + IF( NB.GE.NRHS ) THEN + CALL DPTTS2( N, NRHS, D, E, B, LDB ) + ELSE + DO 10 J = 1, NRHS, NB + JB = MIN( NRHS-J+1, NB ) + CALL DPTTS2( N, JB, D, E, B( 1, J ), LDB ) + 10 CONTINUE + END IF +* + RETURN +* +* End of DPTTRS +* + END diff --git a/libcruft/lapack/dptts2.f b/libcruft/lapack/dptts2.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/dptts2.f @@ -0,0 +1,94 @@ + SUBROUTINE DPTTS2( N, NRHS, D, E, B, LDB ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + INTEGER LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTTS2 solves a tridiagonal system of the form +* A * X = B +* using the L*D*L' factorization of A computed by DPTTRF. D is a +* diagonal matrix specified in the vector D, L is a unit bidiagonal +* matrix whose subdiagonal is specified in the vector E, and X and B +* are N by NRHS matrices. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the tridiagonal matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the diagonal matrix D from the +* L*D*L' factorization of A. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) subdiagonal elements of the unit bidiagonal factor +* L from the L*D*L' factorization of A. E can also be regarded +* as the superdiagonal of the unit bidiagonal factor U from the +* factorization A = U'*D*U. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side vectors B for the system of +* linear equations. +* On exit, the solution vectors, X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Subroutines .. + EXTERNAL DSCAL +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.1 ) THEN + IF( N.EQ.1 ) + $ CALL DSCAL( NRHS, 1.D0 / D( 1 ), B, LDB ) + RETURN + END IF +* +* Solve A * X = B using the factorization A = L*D*L', +* overwriting each right hand side vector with its solution. +* + DO 30 J = 1, NRHS +* +* Solve L * x = b. +* + DO 10 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*E( I-1 ) + 10 CONTINUE +* +* Solve D * L' * x = b. +* + B( N, J ) = B( N, J ) / D( N ) + DO 20 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) / D( I ) - B( I+1, J )*E( I ) + 20 CONTINUE + 30 CONTINUE +* + RETURN +* +* End of DPTTS2 +* + END diff --git a/libcruft/lapack/zgbcon.f b/libcruft/lapack/zgbcon.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgbcon.f @@ -0,0 +1,230 @@ + SUBROUTINE ZGBCON( NORM, N, KL, KU, AB, LDAB, IPIV, ANORM, RCOND, + $ WORK, RWORK, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER INFO, KL, KU, LDAB, N + DOUBLE PRECISION ANORM, RCOND +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION RWORK( * ) + COMPLEX*16 AB( LDAB, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* ZGBCON estimates the reciprocal of the condition number of a complex +* general band matrix A, in either the 1-norm or the infinity-norm, +* using the LU factorization computed by ZGBTRF. +* +* An estimate is obtained for norm(inv(A)), and the reciprocal of the +* condition number is computed as +* RCOND = 1 / ( norm(A) * norm(inv(A)) ). +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies whether the 1-norm condition number or the +* infinity-norm condition number is required: +* = '1' or 'O': 1-norm; +* = 'I': Infinity-norm. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input) COMPLEX*16 array, dimension (LDAB,N) +* Details of the LU factorization of the band matrix A, as +* computed by ZGBTRF. U is stored as an upper triangular band +* matrix with KL+KU superdiagonals in rows 1 to KL+KU+1, and +* the multipliers used during the factorization are stored in +* rows KL+KU+2 to 2*KL+KU+1. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= N, row i of the matrix was +* interchanged with row IPIV(i). +* +* ANORM (input) DOUBLE PRECISION +* If NORM = '1' or 'O', the 1-norm of the original matrix A. +* If NORM = 'I', the infinity-norm of the original matrix A. +* +* RCOND (output) DOUBLE PRECISION +* The reciprocal of the condition number of the matrix A, +* computed as RCOND = 1/(norm(A) * norm(inv(A))). +* +* WORK (workspace) COMPLEX*16 array, dimension (2*N) +* +* RWORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LNOTI, ONENRM + CHARACTER NORMIN + INTEGER IX, J, JP, KASE, KASE1, KD, LM + DOUBLE PRECISION AINVNM, SCALE, SMLNUM + COMPLEX*16 T, ZDUM +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IZAMAX + DOUBLE PRECISION DLAMCH + COMPLEX*16 ZDOTC + EXTERNAL LSAME, IZAMAX, DLAMCH, ZDOTC +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZAXPY, ZDRSCL, ZLACON, ZLATBS +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, DIMAG, MIN +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + ONENRM = NORM.EQ.'1' .OR. LSAME( NORM, 'O' ) + IF( .NOT.ONENRM .AND. .NOT.LSAME( NORM, 'I' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.2*KL+KU+1 ) THEN + INFO = -6 + ELSE IF( ANORM.LT.ZERO ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGBCON', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + RCOND = ZERO + IF( N.EQ.0 ) THEN + RCOND = ONE + RETURN + ELSE IF( ANORM.EQ.ZERO ) THEN + RETURN + END IF +* + SMLNUM = DLAMCH( 'Safe minimum' ) +* +* Estimate the norm of inv(A). +* + AINVNM = ZERO + NORMIN = 'N' + IF( ONENRM ) THEN + KASE1 = 1 + ELSE + KASE1 = 2 + END IF + KD = KL + KU + 1 + LNOTI = KL.GT.0 + KASE = 0 + 10 CONTINUE + CALL ZLACON( N, WORK( N+1 ), WORK, AINVNM, KASE ) + IF( KASE.NE.0 ) THEN + IF( KASE.EQ.KASE1 ) THEN +* +* Multiply by inv(L). +* + IF( LNOTI ) THEN + DO 20 J = 1, N - 1 + LM = MIN( KL, N-J ) + JP = IPIV( J ) + T = WORK( JP ) + IF( JP.NE.J ) THEN + WORK( JP ) = WORK( J ) + WORK( J ) = T + END IF + CALL ZAXPY( LM, -T, AB( KD+1, J ), 1, WORK( J+1 ), 1 ) + 20 CONTINUE + END IF +* +* Multiply by inv(U). +* + CALL ZLATBS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N, + $ KL+KU, AB, LDAB, WORK, SCALE, RWORK, INFO ) + ELSE +* +* Multiply by inv(U'). +* + CALL ZLATBS( 'Upper', 'Conjugate transpose', 'Non-unit', + $ NORMIN, N, KL+KU, AB, LDAB, WORK, SCALE, RWORK, + $ INFO ) +* +* Multiply by inv(L'). +* + IF( LNOTI ) THEN + DO 30 J = N - 1, 1, -1 + LM = MIN( KL, N-J ) + WORK( J ) = WORK( J ) - ZDOTC( LM, AB( KD+1, J ), 1, + $ WORK( J+1 ), 1 ) + JP = IPIV( J ) + IF( JP.NE.J ) THEN + T = WORK( JP ) + WORK( JP ) = WORK( J ) + WORK( J ) = T + END IF + 30 CONTINUE + END IF + END IF +* +* Divide X by 1/SCALE if doing so will not cause overflow. +* + NORMIN = 'Y' + IF( SCALE.NE.ONE ) THEN + IX = IZAMAX( N, WORK, 1 ) + IF( SCALE.LT.CABS1( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO ) + $ GO TO 40 + CALL ZDRSCL( N, SCALE, WORK, 1 ) + END IF + GO TO 10 + END IF +* +* Compute the estimate of the reciprocal condition number. +* + IF( AINVNM.NE.ZERO ) + $ RCOND = ( ONE / AINVNM ) / ANORM +* + 40 CONTINUE + RETURN +* +* End of ZGBCON +* + END diff --git a/libcruft/lapack/zgbtf2.f b/libcruft/lapack/zgbtf2.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgbtf2.f @@ -0,0 +1,203 @@ + SUBROUTINE ZGBTF2( M, N, KL, KU, AB, LDAB, IPIV, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, KL, KU, LDAB, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* ZGBTF2 computes an LU factorization of a complex m-by-n band matrix +* A using partial pivoting with row interchanges. +* +* This is the unblocked version of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input/output) COMPLEX*16 array, dimension (LDAB,N) +* On entry, the matrix A in band storage, in rows KL+1 to +* 2*KL+KU+1; rows 1 to KL of the array need not be set. +* The j-th column of A is stored in the j-th column of the +* array AB as follows: +* AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) +* +* On exit, details of the factorization: U is stored as an +* upper triangular band matrix with KL+KU superdiagonals in +* rows 1 to KL+KU+1, and the multipliers used during the +* factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +* See below for further details. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = +i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* M = N = 6, KL = 2, KU = 1: +* +* On entry: On exit: +* +* * * * + + + * * * u14 u25 u36 +* * * + + + + * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 * +* a31 a42 a53 a64 * * m31 m42 m53 m64 * * +* +* Array elements marked * are not used by the routine; elements marked +* + need not be set on entry, but are required by the routine to store +* elements of U, because of fill-in resulting from the row +* interchanges. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE, ZERO + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ), + $ ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + INTEGER I, J, JP, JU, KM, KV +* .. +* .. External Functions .. + INTEGER IZAMAX + EXTERNAL IZAMAX +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGERU, ZSCAL, ZSWAP +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* KV is the number of superdiagonals in the factor U, allowing for +* fill-in. +* + KV = KU + KL +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KL+KV+1 ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGBTF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Gaussian elimination with partial pivoting +* +* Set fill-in elements in columns KU+2 to KV to zero. +* + DO 20 J = KU + 2, MIN( KV, N ) + DO 10 I = KV - J + 2, KL + AB( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* JU is the index of the last column affected by the current stage +* of the factorization. +* + JU = 1 +* + DO 40 J = 1, MIN( M, N ) +* +* Set fill-in elements in column J+KV to zero. +* + IF( J+KV.LE.N ) THEN + DO 30 I = 1, KL + AB( I, J+KV ) = ZERO + 30 CONTINUE + END IF +* +* Find pivot and test for singularity. KM is the number of +* subdiagonal elements in the current column. +* + KM = MIN( KL, M-J ) + JP = IZAMAX( KM+1, AB( KV+1, J ), 1 ) + IPIV( J ) = JP + J - 1 + IF( AB( KV+JP, J ).NE.ZERO ) THEN + JU = MAX( JU, MIN( J+KU+JP-1, N ) ) +* +* Apply interchange to columns J to JU. +* + IF( JP.NE.1 ) + $ CALL ZSWAP( JU-J+1, AB( KV+JP, J ), LDAB-1, + $ AB( KV+1, J ), LDAB-1 ) + IF( KM.GT.0 ) THEN +* +* Compute multipliers. +* + CALL ZSCAL( KM, ONE / AB( KV+1, J ), AB( KV+2, J ), 1 ) +* +* Update trailing submatrix within the band. +* + IF( JU.GT.J ) + $ CALL ZGERU( KM, JU-J, -ONE, AB( KV+2, J ), 1, + $ AB( KV, J+1 ), LDAB-1, AB( KV+1, J+1 ), + $ LDAB-1 ) + END IF + ELSE +* +* If pivot is zero, set INFO to the index of the pivot +* unless a zero pivot has already been found. +* + IF( INFO.EQ.0 ) + $ INFO = J + END IF + 40 CONTINUE + RETURN +* +* End of ZGBTF2 +* + END diff --git a/libcruft/lapack/zgbtrf.f b/libcruft/lapack/zgbtrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgbtrf.f @@ -0,0 +1,443 @@ + SUBROUTINE ZGBTRF( M, N, KL, KU, AB, LDAB, IPIV, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, KL, KU, LDAB, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* ZGBTRF computes an LU factorization of a complex m-by-n band matrix A +* using partial pivoting with row interchanges. +* +* This is the blocked version of the algorithm, calling Level 3 BLAS. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input/output) COMPLEX*16 array, dimension (LDAB,N) +* On entry, the matrix A in band storage, in rows KL+1 to +* 2*KL+KU+1; rows 1 to KL of the array need not be set. +* The j-th column of A is stored in the j-th column of the +* array AB as follows: +* AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) +* +* On exit, details of the factorization: U is stored as an +* upper triangular band matrix with KL+KU superdiagonals in +* rows 1 to KL+KU+1, and the multipliers used during the +* factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +* See below for further details. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = +i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* M = N = 6, KL = 2, KU = 1: +* +* On entry: On exit: +* +* * * * + + + * * * u14 u25 u36 +* * * + + + + * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 * +* a31 a42 a53 a64 * * m31 m42 m53 m64 * * +* +* Array elements marked * are not used by the routine; elements marked +* + need not be set on entry, but are required by the routine to store +* elements of U because of fill-in resulting from the row interchanges. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE, ZERO + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ), + $ ZERO = ( 0.0D+0, 0.0D+0 ) ) + INTEGER NBMAX, LDWORK + PARAMETER ( NBMAX = 64, LDWORK = NBMAX+1 ) +* .. +* .. Local Scalars .. + INTEGER I, I2, I3, II, IP, J, J2, J3, JB, JJ, JM, JP, + $ JU, K2, KM, KV, NB, NW + COMPLEX*16 TEMP +* .. +* .. Local Arrays .. + COMPLEX*16 WORK13( LDWORK, NBMAX ), + $ WORK31( LDWORK, NBMAX ) +* .. +* .. External Functions .. + INTEGER ILAENV, IZAMAX + EXTERNAL ILAENV, IZAMAX +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZCOPY, ZGBTF2, ZGEMM, ZGERU, ZLASWP, + $ ZSCAL, ZSWAP, ZTRSM +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* KV is the number of superdiagonals in the factor U, allowing for +* fill-in +* + KV = KU + KL +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KL+KV+1 ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGBTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment +* + NB = ILAENV( 1, 'ZGBTRF', ' ', M, N, KL, KU ) +* +* The block size must not exceed the limit set by the size of the +* local arrays WORK13 and WORK31. +* + NB = MIN( NB, NBMAX ) +* + IF( NB.LE.1 .OR. NB.GT.KL ) THEN +* +* Use unblocked code +* + CALL ZGBTF2( M, N, KL, KU, AB, LDAB, IPIV, INFO ) + ELSE +* +* Use blocked code +* +* Zero the superdiagonal elements of the work array WORK13 +* + DO 20 J = 1, NB + DO 10 I = 1, J - 1 + WORK13( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* Zero the subdiagonal elements of the work array WORK31 +* + DO 40 J = 1, NB + DO 30 I = J + 1, NB + WORK31( I, J ) = ZERO + 30 CONTINUE + 40 CONTINUE +* +* Gaussian elimination with partial pivoting +* +* Set fill-in elements in columns KU+2 to KV to zero +* + DO 60 J = KU + 2, MIN( KV, N ) + DO 50 I = KV - J + 2, KL + AB( I, J ) = ZERO + 50 CONTINUE + 60 CONTINUE +* +* JU is the index of the last column affected by the current +* stage of the factorization +* + JU = 1 +* + DO 180 J = 1, MIN( M, N ), NB + JB = MIN( NB, MIN( M, N )-J+1 ) +* +* The active part of the matrix is partitioned +* +* A11 A12 A13 +* A21 A22 A23 +* A31 A32 A33 +* +* Here A11, A21 and A31 denote the current block of JB columns +* which is about to be factorized. The number of rows in the +* partitioning are JB, I2, I3 respectively, and the numbers +* of columns are JB, J2, J3. The superdiagonal elements of A13 +* and the subdiagonal elements of A31 lie outside the band. +* + I2 = MIN( KL-JB, M-J-JB+1 ) + I3 = MIN( JB, M-J-KL+1 ) +* +* J2 and J3 are computed after JU has been updated. +* +* Factorize the current block of JB columns +* + DO 80 JJ = J, J + JB - 1 +* +* Set fill-in elements in column JJ+KV to zero +* + IF( JJ+KV.LE.N ) THEN + DO 70 I = 1, KL + AB( I, JJ+KV ) = ZERO + 70 CONTINUE + END IF +* +* Find pivot and test for singularity. KM is the number of +* subdiagonal elements in the current column. +* + KM = MIN( KL, M-JJ ) + JP = IZAMAX( KM+1, AB( KV+1, JJ ), 1 ) + IPIV( JJ ) = JP + JJ - J + IF( AB( KV+JP, JJ ).NE.ZERO ) THEN + JU = MAX( JU, MIN( JJ+KU+JP-1, N ) ) + IF( JP.NE.1 ) THEN +* +* Apply interchange to columns J to J+JB-1 +* + IF( JP+JJ-1.LT.J+KL ) THEN +* + CALL ZSWAP( JB, AB( KV+1+JJ-J, J ), LDAB-1, + $ AB( KV+JP+JJ-J, J ), LDAB-1 ) + ELSE +* +* The interchange affects columns J to JJ-1 of A31 +* which are stored in the work array WORK31 +* + CALL ZSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ WORK31( JP+JJ-J-KL, 1 ), LDWORK ) + CALL ZSWAP( J+JB-JJ, AB( KV+1, JJ ), LDAB-1, + $ AB( KV+JP, JJ ), LDAB-1 ) + END IF + END IF +* +* Compute multipliers +* + CALL ZSCAL( KM, ONE / AB( KV+1, JJ ), AB( KV+2, JJ ), + $ 1 ) +* +* Update trailing submatrix within the band and within +* the current block. JM is the index of the last column +* which needs to be updated. +* + JM = MIN( JU, J+JB-1 ) + IF( JM.GT.JJ ) + $ CALL ZGERU( KM, JM-JJ, -ONE, AB( KV+2, JJ ), 1, + $ AB( KV, JJ+1 ), LDAB-1, + $ AB( KV+1, JJ+1 ), LDAB-1 ) + ELSE +* +* If pivot is zero, set INFO to the index of the pivot +* unless a zero pivot has already been found. +* + IF( INFO.EQ.0 ) + $ INFO = JJ + END IF +* +* Copy current column of A31 into the work array WORK31 +* + NW = MIN( JJ-J+1, I3 ) + IF( NW.GT.0 ) + $ CALL ZCOPY( NW, AB( KV+KL+1-JJ+J, JJ ), 1, + $ WORK31( 1, JJ-J+1 ), 1 ) + 80 CONTINUE + IF( J+JB.LE.N ) THEN +* +* Apply the row interchanges to the other blocks. +* + J2 = MIN( JU-J+1, KV ) - JB + J3 = MAX( 0, JU-J-KV+1 ) +* +* Use ZLASWP to apply the row interchanges to A12, A22, and +* A32. +* + CALL ZLASWP( J2, AB( KV+1-JB, J+JB ), LDAB-1, 1, JB, + $ IPIV( J ), 1 ) +* +* Adjust the pivot indices. +* + DO 90 I = J, J + JB - 1 + IPIV( I ) = IPIV( I ) + J - 1 + 90 CONTINUE +* +* Apply the row interchanges to A13, A23, and A33 +* columnwise. +* + K2 = J - 1 + JB + J2 + DO 110 I = 1, J3 + JJ = K2 + I + DO 100 II = J + I - 1, J + JB - 1 + IP = IPIV( II ) + IF( IP.NE.II ) THEN + TEMP = AB( KV+1+II-JJ, JJ ) + AB( KV+1+II-JJ, JJ ) = AB( KV+1+IP-JJ, JJ ) + AB( KV+1+IP-JJ, JJ ) = TEMP + END IF + 100 CONTINUE + 110 CONTINUE +* +* Update the relevant part of the trailing submatrix +* + IF( J2.GT.0 ) THEN +* +* Update A12 +* + CALL ZTRSM( 'Left', 'Lower', 'No transpose', 'Unit', + $ JB, J2, ONE, AB( KV+1, J ), LDAB-1, + $ AB( KV+1-JB, J+JB ), LDAB-1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A22 +* + CALL ZGEMM( 'No transpose', 'No transpose', I2, J2, + $ JB, -ONE, AB( KV+1+JB, J ), LDAB-1, + $ AB( KV+1-JB, J+JB ), LDAB-1, ONE, + $ AB( KV+1, J+JB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Update A32 +* + CALL ZGEMM( 'No transpose', 'No transpose', I3, J2, + $ JB, -ONE, WORK31, LDWORK, + $ AB( KV+1-JB, J+JB ), LDAB-1, ONE, + $ AB( KV+KL+1-JB, J+JB ), LDAB-1 ) + END IF + END IF +* + IF( J3.GT.0 ) THEN +* +* Copy the lower triangle of A13 into the work array +* WORK13 +* + DO 130 JJ = 1, J3 + DO 120 II = JJ, JB + WORK13( II, JJ ) = AB( II-JJ+1, JJ+J+KV-1 ) + 120 CONTINUE + 130 CONTINUE +* +* Update A13 in the work array +* + CALL ZTRSM( 'Left', 'Lower', 'No transpose', 'Unit', + $ JB, J3, ONE, AB( KV+1, J ), LDAB-1, + $ WORK13, LDWORK ) +* + IF( I2.GT.0 ) THEN +* +* Update A23 +* + CALL ZGEMM( 'No transpose', 'No transpose', I2, J3, + $ JB, -ONE, AB( KV+1+JB, J ), LDAB-1, + $ WORK13, LDWORK, ONE, AB( 1+JB, J+KV ), + $ LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Update A33 +* + CALL ZGEMM( 'No transpose', 'No transpose', I3, J3, + $ JB, -ONE, WORK31, LDWORK, WORK13, + $ LDWORK, ONE, AB( 1+KL, J+KV ), LDAB-1 ) + END IF +* +* Copy the lower triangle of A13 back into place +* + DO 150 JJ = 1, J3 + DO 140 II = JJ, JB + AB( II-JJ+1, JJ+J+KV-1 ) = WORK13( II, JJ ) + 140 CONTINUE + 150 CONTINUE + END IF + ELSE +* +* Adjust the pivot indices. +* + DO 160 I = J, J + JB - 1 + IPIV( I ) = IPIV( I ) + J - 1 + 160 CONTINUE + END IF +* +* Partially undo the interchanges in the current block to +* restore the upper triangular form of A31 and copy the upper +* triangle of A31 back into place +* + DO 170 JJ = J + JB - 1, J, -1 + JP = IPIV( JJ ) - JJ + 1 + IF( JP.NE.1 ) THEN +* +* Apply interchange to columns J to JJ-1 +* + IF( JP+JJ-1.LT.J+KL ) THEN +* +* The interchange does not affect A31 +* + CALL ZSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ AB( KV+JP+JJ-J, J ), LDAB-1 ) + ELSE +* +* The interchange does affect A31 +* + CALL ZSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ WORK31( JP+JJ-J-KL, 1 ), LDWORK ) + END IF + END IF +* +* Copy the current column of A31 back into place +* + NW = MIN( I3, JJ-J+1 ) + IF( NW.GT.0 ) + $ CALL ZCOPY( NW, WORK31( 1, JJ-J+1 ), 1, + $ AB( KV+KL+1-JJ+J, JJ ), 1 ) + 170 CONTINUE + 180 CONTINUE + END IF +* + RETURN +* +* End of ZGBTRF +* + END diff --git a/libcruft/lapack/zgbtrs.f b/libcruft/lapack/zgbtrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgbtrs.f @@ -0,0 +1,215 @@ + SUBROUTINE ZGBTRS( TRANS, N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, KL, KU, LDAB, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 AB( LDAB, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZGBTRS solves a system of linear equations +* A * X = B, A**T * X = B, or A**H * X = B +* with a general band matrix A using the LU factorization computed +* by ZGBTRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER*1 +* Specifies the form of the system of equations. +* = 'N': A * X = B (No transpose) +* = 'T': A**T * X = B (Transpose) +* = 'C': A**H * X = B (Conjugate transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* AB (input) COMPLEX*16 array, dimension (LDAB,N) +* Details of the LU factorization of the band matrix A, as +* computed by ZGBTRF. U is stored as an upper triangular band +* matrix with KL+KU superdiagonals in rows 1 to KL+KU+1, and +* the multipliers used during the factorization are stored in +* rows KL+KU+2 to 2*KL+KU+1. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= N, row i of the matrix was +* interchanged with row IPIV(i). +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + LOGICAL LNOTI, NOTRAN + INTEGER I, J, KD, L, LM +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGEMV, ZGERU, ZLACGV, ZSWAP, ZTBSV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -5 + ELSE IF( LDAB.LT.( 2*KL+KU+1 ) ) THEN + INFO = -7 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGBTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + KD = KU + KL + 1 + LNOTI = KL.GT.0 +* + IF( NOTRAN ) THEN +* +* Solve A*X = B. +* +* Solve L*X = B, overwriting B with X. +* +* L is represented as a product of permutations and unit lower +* triangular matrices L = P(1) * L(1) * ... * P(n-1) * L(n-1), +* where each transformation L(i) is a rank-one modification of +* the identity matrix. +* + IF( LNOTI ) THEN + DO 10 J = 1, N - 1 + LM = MIN( KL, N-J ) + L = IPIV( J ) + IF( L.NE.J ) + $ CALL ZSWAP( NRHS, B( L, 1 ), LDB, B( J, 1 ), LDB ) + CALL ZGERU( LM, NRHS, -ONE, AB( KD+1, J ), 1, B( J, 1 ), + $ LDB, B( J+1, 1 ), LDB ) + 10 CONTINUE + END IF +* + DO 20 I = 1, NRHS +* +* Solve U*X = B, overwriting B with X. +* + CALL ZTBSV( 'Upper', 'No transpose', 'Non-unit', N, KL+KU, + $ AB, LDAB, B( 1, I ), 1 ) + 20 CONTINUE +* + ELSE IF( LSAME( TRANS, 'T' ) ) THEN +* +* Solve A**T * X = B. +* + DO 30 I = 1, NRHS +* +* Solve U**T * X = B, overwriting B with X. +* + CALL ZTBSV( 'Upper', 'Transpose', 'Non-unit', N, KL+KU, AB, + $ LDAB, B( 1, I ), 1 ) + 30 CONTINUE +* +* Solve L**T * X = B, overwriting B with X. +* + IF( LNOTI ) THEN + DO 40 J = N - 1, 1, -1 + LM = MIN( KL, N-J ) + CALL ZGEMV( 'Transpose', LM, NRHS, -ONE, B( J+1, 1 ), + $ LDB, AB( KD+1, J ), 1, ONE, B( J, 1 ), LDB ) + L = IPIV( J ) + IF( L.NE.J ) + $ CALL ZSWAP( NRHS, B( L, 1 ), LDB, B( J, 1 ), LDB ) + 40 CONTINUE + END IF +* + ELSE +* +* Solve A**H * X = B. +* + DO 50 I = 1, NRHS +* +* Solve U**H * X = B, overwriting B with X. +* + CALL ZTBSV( 'Upper', 'Conjugate transpose', 'Non-unit', N, + $ KL+KU, AB, LDAB, B( 1, I ), 1 ) + 50 CONTINUE +* +* Solve L**H * X = B, overwriting B with X. +* + IF( LNOTI ) THEN + DO 60 J = N - 1, 1, -1 + LM = MIN( KL, N-J ) + CALL ZLACGV( NRHS, B( J, 1 ), LDB ) + CALL ZGEMV( 'Conjugate transpose', LM, NRHS, -ONE, + $ B( J+1, 1 ), LDB, AB( KD+1, J ), 1, ONE, + $ B( J, 1 ), LDB ) + CALL ZLACGV( NRHS, B( J, 1 ), LDB ) + L = IPIV( J ) + IF( L.NE.J ) + $ CALL ZSWAP( NRHS, B( L, 1 ), LDB, B( J, 1 ), LDB ) + 60 CONTINUE + END IF + END IF + RETURN +* +* End of ZGBTRS +* + END diff --git a/libcruft/lapack/zgtsv.f b/libcruft/lapack/zgtsv.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgtsv.f @@ -0,0 +1,174 @@ + SUBROUTINE ZGTSV( N, NRHS, DL, D, DU, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + COMPLEX*16 B( LDB, * ), D( * ), DL( * ), DU( * ) +* .. +* +* Purpose +* ======= +* +* ZGTSV solves the equation +* +* A*X = B, +* +* where A is an N-by-N tridiagonal matrix, by Gaussian elimination with +* partial pivoting. +* +* Note that the equation A'*X = B may be solved by interchanging the +* order of the arguments DU and DL. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* DL (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, DL must contain the (n-1) subdiagonal elements of +* A. +* On exit, DL is overwritten by the (n-2) elements of the +* second superdiagonal of the upper triangular matrix U from +* the LU factorization of A, in DL(1), ..., DL(n-2). +* +* D (input/output) COMPLEX*16 array, dimension (N) +* On entry, D must contain the diagonal elements of A. +* On exit, D is overwritten by the n diagonal elements of U. +* +* DU (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, DU must contain the (n-1) superdiagonal elements +* of A. +* On exit, DU is overwritten by the (n-1) elements of the first +* superdiagonal of U. +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the N-by-NRHS right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero, and the solution +* has not been computed. The factorization has not been +* completed unless i = N. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + INTEGER J, K + COMPLEX*16 MULT, TEMP, ZDUM +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, DIMAG, MAX +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGTSV ', -INFO ) + RETURN + END IF +* + IF( N.EQ.0 ) + $ RETURN +* + DO 30 K = 1, N - 1 + IF( DL( K ).EQ.ZERO ) THEN +* +* Subdiagonal is zero, no elimination is required. +* + IF( D( K ).EQ.ZERO ) THEN +* +* Diagonal is zero: set INFO = K and return; a unique +* solution can not be found. +* + INFO = K + RETURN + END IF + ELSE IF( CABS1( D( K ) ).GE.CABS1( DL( K ) ) ) THEN +* +* No row interchange required +* + MULT = DL( K ) / D( K ) + D( K+1 ) = D( K+1 ) - MULT*DU( K ) + DO 10 J = 1, NRHS + B( K+1, J ) = B( K+1, J ) - MULT*B( K, J ) + 10 CONTINUE + IF( K.LT.( N-1 ) ) + $ DL( K ) = ZERO + ELSE +* +* Interchange rows K and K+1 +* + MULT = D( K ) / DL( K ) + D( K ) = DL( K ) + TEMP = D( K+1 ) + D( K+1 ) = DU( K ) - MULT*TEMP + IF( K.LT.( N-1 ) ) THEN + DL( K ) = DU( K+1 ) + DU( K+1 ) = -MULT*DL( K ) + END IF + DU( K ) = TEMP + DO 20 J = 1, NRHS + TEMP = B( K, J ) + B( K, J ) = B( K+1, J ) + B( K+1, J ) = TEMP - MULT*B( K+1, J ) + 20 CONTINUE + END IF + 30 CONTINUE + IF( D( N ).EQ.ZERO ) THEN + INFO = N + RETURN + END IF +* +* Back solve with the matrix U from the factorization. +* + DO 50 J = 1, NRHS + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / D( N-1 ) + DO 40 K = N - 2, 1, -1 + B( K, J ) = ( B( K, J )-DU( K )*B( K+1, J )-DL( K )* + $ B( K+2, J ) ) / D( K ) + 40 CONTINUE + 50 CONTINUE +* + RETURN +* +* End of ZGTSV +* + END diff --git a/libcruft/lapack/zgttrf.f b/libcruft/lapack/zgttrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgttrf.f @@ -0,0 +1,155 @@ + SUBROUTINE ZGTTRF( N, DL, D, DU, DU2, IPIV, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* ZGTTRF computes an LU factorization of a complex tridiagonal matrix A +* using elimination with partial pivoting and row interchanges. +* +* The factorization has the form +* A = L * U +* where L is a product of permutation and unit lower bidiagonal +* matrices and U is upper triangular with nonzeros in only the main +* diagonal and first two superdiagonals. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* DL (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, DL must contain the (n-1) subdiagonal elements of +* A. +* On exit, DL is overwritten by the (n-1) multipliers that +* define the matrix L from the LU factorization of A. +* +* D (input/output) COMPLEX*16 array, dimension (N) +* On entry, D must contain the diagonal elements of A. +* On exit, D is overwritten by the n diagonal elements of the +* upper triangular matrix U from the LU factorization of A. +* +* DU (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, DU must contain the (n-1) superdiagonal elements +* of A. +* On exit, DU is overwritten by the (n-1) elements of the first +* superdiagonal of U. +* +* DU2 (output) COMPLEX*16 array, dimension (N-2) +* On exit, DU2 is overwritten by the (n-2) elements of the +* second superdiagonal of U. +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I + COMPLEX*16 FACT, TEMP, ZDUM +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, DIMAG +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Parameters .. + COMPLEX*16 CZERO + PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'ZGTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Initialize IPIV(i) = i +* + DO 10 I = 1, N + IPIV( I ) = I + 10 CONTINUE +* + DO 20 I = 1, N - 1 + IF( DL( I ).EQ.CZERO ) THEN +* +* Subdiagonal is zero, no elimination is required. +* + IF( D( I ).EQ.CZERO .AND. INFO.EQ.0 ) + $ INFO = I + IF( I.LT.N-1 ) + $ DU2( I ) = CZERO + ELSE IF( CABS1( D( I ) ).GE.CABS1( DL( I ) ) ) THEN +* +* No row interchange required, eliminate DL(I) +* + FACT = DL( I ) / D( I ) + DL( I ) = FACT + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + IF( I.LT.N-1 ) + $ DU2( I ) = CZERO + ELSE +* +* Interchange rows I and I+1, eliminate DL(I) +* + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + DL( I ) = FACT + TEMP = DU( I ) + DU( I ) = D( I+1 ) + D( I+1 ) = TEMP - FACT*D( I+1 ) + IF( I.LT.N-1 ) THEN + DU2( I ) = DU( I+1 ) + DU( I+1 ) = -FACT*DU( I+1 ) + END IF + IPIV( I ) = IPIV( I ) + 1 + END IF + 20 CONTINUE + IF( D( N ).EQ.CZERO .AND. INFO.EQ.0 ) THEN + INFO = N + RETURN + END IF +* + RETURN +* +* End of ZGTTRF +* + END diff --git a/libcruft/lapack/zgttrs.f b/libcruft/lapack/zgttrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zgttrs.f @@ -0,0 +1,206 @@ + SUBROUTINE ZGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 B( LDB, * ), D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* ZGTTRS solves one of the systems of equations +* A * X = B, A**T * X = B, or A**H * X = B, +* with a tridiagonal matrix A using the LU factorization computed +* by ZGTTRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A**T * X = B (Transpose) +* = 'C': A**H * X = B (Conjugate transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* DL (input) COMPLEX*16 array, dimension (N-1) +* The (n-1) multipliers that define the matrix L from the +* LU factorization of A. +* +* D (input) COMPLEX*16 array, dimension (N) +* The n diagonal elements of the upper triangular matrix U from +* the LU factorization of A. +* +* DU (input) COMPLEX*16 array, dimension (N-1) +* The (n-1) elements of the first superdiagonal of U. +* +* DU2 (input) COMPLEX*16 array, dimension (N-2) +* The (n-2) elements of the second superdiagonal of U. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, B is overwritten by the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL NOTRAN + INTEGER I, J + COMPLEX*16 TEMP +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. +* .. Executable Statements .. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDB.LT.MAX( N, 1 ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( NOTRAN ) THEN +* +* Solve A*X = B using the LU factorization of A, +* overwriting each right hand side vector with its solution. +* + DO 30 J = 1, NRHS +* +* Solve L*x = b. +* + DO 10 I = 1, N - 1 + IF( IPIV( I ).EQ.I ) THEN + B( I+1, J ) = B( I+1, J ) - DL( I )*B( I, J ) + ELSE + TEMP = B( I, J ) + B( I, J ) = B( I+1, J ) + B( I+1, J ) = TEMP - DL( I )*B( I, J ) + END IF + 10 CONTINUE +* +* Solve U*x = b. +* + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / + $ D( N-1 ) + DO 20 I = N - 2, 1, -1 + B( I, J ) = ( B( I, J )-DU( I )*B( I+1, J )-DU2( I )* + $ B( I+2, J ) ) / D( I ) + 20 CONTINUE + 30 CONTINUE + ELSE IF( LSAME( TRANS, 'T' ) ) THEN +* +* Solve A**T * X = B. +* + DO 60 J = 1, NRHS +* +* Solve U**T * x = b. +* + B( 1, J ) = B( 1, J ) / D( 1 ) + IF( N.GT.1 ) + $ B( 2, J ) = ( B( 2, J )-DU( 1 )*B( 1, J ) ) / D( 2 ) + DO 40 I = 3, N + B( I, J ) = ( B( I, J )-DU( I-1 )*B( I-1, J )-DU2( I-2 )* + $ B( I-2, J ) ) / D( I ) + 40 CONTINUE +* +* Solve L**T * x = b. +* + DO 50 I = N - 1, 1, -1 + IF( IPIV( I ).EQ.I ) THEN + B( I, J ) = B( I, J ) - DL( I )*B( I+1, J ) + ELSE + TEMP = B( I+1, J ) + B( I+1, J ) = B( I, J ) - DL( I )*TEMP + B( I, J ) = TEMP + END IF + 50 CONTINUE + 60 CONTINUE + ELSE +* +* Solve A**H * X = B. +* + DO 90 J = 1, NRHS +* +* Solve U**H * x = b. +* + B( 1, J ) = B( 1, J ) / DCONJG( D( 1 ) ) + IF( N.GT.1 ) + $ B( 2, J ) = ( B( 2, J )-DCONJG( DU( 1 ) )*B( 1, J ) ) / + $ DCONJG( D( 2 ) ) + DO 70 I = 3, N + B( I, J ) = ( B( I, J )-DCONJG( DU( I-1 ) )*B( I-1, J )- + $ DCONJG( DU2( I-2 ) )*B( I-2, J ) ) / + $ DCONJG( D( I ) ) + 70 CONTINUE +* +* Solve L**H * x = b. +* + DO 80 I = N - 1, 1, -1 + IF( IPIV( I ).EQ.I ) THEN + B( I, J ) = B( I, J ) - DCONJG( DL( I ) )*B( I+1, J ) + ELSE + TEMP = B( I+1, J ) + B( I+1, J ) = B( I, J ) - DCONJG( DL( I ) )*TEMP + B( I, J ) = TEMP + END IF + 80 CONTINUE + 90 CONTINUE + END IF +* +* End of ZGTTRS +* + END diff --git a/libcruft/lapack/zlatbs.f b/libcruft/lapack/zlatbs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zlatbs.f @@ -0,0 +1,909 @@ + SUBROUTINE ZLATBS( UPLO, TRANS, DIAG, NORMIN, N, KD, AB, LDAB, X, + $ SCALE, CNORM, INFO ) +* +* -- LAPACK auxiliary routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1992 +* +* .. Scalar Arguments .. + CHARACTER DIAG, NORMIN, TRANS, UPLO + INTEGER INFO, KD, LDAB, N + DOUBLE PRECISION SCALE +* .. +* .. Array Arguments .. + DOUBLE PRECISION CNORM( * ) + COMPLEX*16 AB( LDAB, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* ZLATBS solves one of the triangular systems +* +* A * x = s*b, A**T * x = s*b, or A**H * x = s*b, +* +* with scaling to prevent overflow, where A is an upper or lower +* triangular band matrix. Here A' denotes the transpose of A, x and b +* are n-element vectors, and s is a scaling factor, usually less than +* or equal to 1, chosen so that the components of x will be less than +* the overflow threshold. If the unscaled problem will not cause +* overflow, the Level 2 BLAS routine ZTBSV is called. If the matrix A +* is singular (A(j,j) = 0 for some j), then s is set to 0 and a +* non-trivial solution to A*x = 0 is returned. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the matrix A is upper or lower triangular. +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* TRANS (input) CHARACTER*1 +* Specifies the operation applied to A. +* = 'N': Solve A * x = s*b (No transpose) +* = 'T': Solve A**T * x = s*b (Transpose) +* = 'C': Solve A**H * x = s*b (Conjugate transpose) +* +* DIAG (input) CHARACTER*1 +* Specifies whether or not the matrix A is unit triangular. +* = 'N': Non-unit triangular +* = 'U': Unit triangular +* +* NORMIN (input) CHARACTER*1 +* Specifies whether CNORM has been set or not. +* = 'Y': CNORM contains the column norms on entry +* = 'N': CNORM is not set on entry. On exit, the norms will +* be computed and stored in CNORM. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of subdiagonals or superdiagonals in the +* triangular matrix A. KD >= 0. +* +* AB (input) COMPLEX*16 array, dimension (LDAB,N) +* The upper or lower triangular band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of A is stored +* in the j-th column of the array AB as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* X (input/output) COMPLEX*16 array, dimension (N) +* On entry, the right hand side b of the triangular system. +* On exit, X is overwritten by the solution vector x. +* +* SCALE (output) DOUBLE PRECISION +* The scaling factor s for the triangular system +* A * x = s*b, A**T * x = s*b, or A**H * x = s*b. +* If SCALE = 0, the matrix A is singular or badly scaled, and +* the vector x is an exact or approximate solution to A*x = 0. +* +* CNORM (input or output) DOUBLE PRECISION array, dimension (N) +* +* If NORMIN = 'Y', CNORM is an input argument and CNORM(j) +* contains the norm of the off-diagonal part of the j-th column +* of A. If TRANS = 'N', CNORM(j) must be greater than or equal +* to the infinity-norm, and if TRANS = 'T' or 'C', CNORM(j) +* must be greater than or equal to the 1-norm. +* +* If NORMIN = 'N', CNORM is an output argument and CNORM(j) +* returns the 1-norm of the offdiagonal part of the j-th column +* of A. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* Further Details +* ======= ======= +* +* A rough bound on x is computed; if that is less than overflow, ZTBSV +* is called, otherwise, specific code is used which checks for possible +* overflow or divide-by-zero at every operation. +* +* A columnwise scheme is used for solving A*x = b. The basic algorithm +* if A is lower triangular is +* +* x[1:n] := b[1:n] +* for j = 1, ..., n +* x(j) := x(j) / A(j,j) +* x[j+1:n] := x[j+1:n] - x(j) * A[j+1:n,j] +* end +* +* Define bounds on the components of x after j iterations of the loop: +* M(j) = bound on x[1:j] +* G(j) = bound on x[j+1:n] +* Initially, let M(0) = 0 and G(0) = max{x(i), i=1,...,n}. +* +* Then for iteration j+1 we have +* M(j+1) <= G(j) / | A(j+1,j+1) | +* G(j+1) <= G(j) + M(j+1) * | A[j+2:n,j+1] | +* <= G(j) ( 1 + CNORM(j+1) / | A(j+1,j+1) | ) +* +* where CNORM(j+1) is greater than or equal to the infinity-norm of +* column j+1 of A, not counting the diagonal. Hence +* +* G(j) <= G(0) product ( 1 + CNORM(i) / | A(i,i) | ) +* 1<=i<=j +* and +* +* |x(j)| <= ( G(0) / |A(j,j)| ) product ( 1 + CNORM(i) / |A(i,i)| ) +* 1<=i< j +* +* Since |x(j)| <= M(j), we use the Level 2 BLAS routine ZTBSV if the +* reciprocal of the largest M(j), j=1,..,n, is larger than +* max(underflow, 1/overflow). +* +* The bound on x(j) is also used to determine when a step in the +* columnwise method can be performed without fear of overflow. If +* the computed bound is greater than a large constant, x is scaled to +* prevent overflow, but if the bound overflows, x is set to 0, x(j) to +* 1, and scale to 0, and a non-trivial solution to A*x = 0 is found. +* +* Similarly, a row-wise scheme is used to solve A**T *x = b or +* A**H *x = b. The basic algorithm for A upper triangular is +* +* for j = 1, ..., n +* x(j) := ( b(j) - A[1:j-1,j]' * x[1:j-1] ) / A(j,j) +* end +* +* We simultaneously compute two bounds +* G(j) = bound on ( b(i) - A[1:i-1,i]' * x[1:i-1] ), 1<=i<=j +* M(j) = bound on x(i), 1<=i<=j +* +* The initial values are G(0) = 0, M(0) = max{b(i), i=1,..,n}, and we +* add the constraint G(j) >= G(j-1) and M(j) >= M(j-1) for j >= 1. +* Then the bound on x(j) is +* +* M(j) <= M(j-1) * ( 1 + CNORM(j) ) / | A(j,j) | +* +* <= M(0) * product ( ( 1 + CNORM(i) ) / |A(i,i)| ) +* 1<=i<=j +* +* and we can safely call ZTBSV if 1/M(n) and 1/G(n) are both greater +* than max(underflow, 1/overflow). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE, TWO + PARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0, + $ TWO = 2.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOTRAN, NOUNIT, UPPER + INTEGER I, IMAX, J, JFIRST, JINC, JLAST, JLEN, MAIND + DOUBLE PRECISION BIGNUM, GROW, REC, SMLNUM, TJJ, TMAX, TSCAL, + $ XBND, XJ, XMAX + COMPLEX*16 CSUMJ, TJJS, USCAL, ZDUM +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX, IZAMAX + DOUBLE PRECISION DLAMCH, DZASUM + COMPLEX*16 ZDOTC, ZDOTU, ZLADIV + EXTERNAL LSAME, IDAMAX, IZAMAX, DLAMCH, DZASUM, ZDOTC, + $ ZDOTU, ZLADIV +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, XERBLA, ZAXPY, ZDSCAL, ZTBSV +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, DCMPLX, DCONJG, DIMAG, MAX, MIN +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1, CABS2 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) + CABS2( ZDUM ) = ABS( DBLE( ZDUM ) / 2.D0 ) + + $ ABS( DIMAG( ZDUM ) / 2.D0 ) +* .. +* .. Executable Statements .. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOTRAN = LSAME( TRANS, 'N' ) + NOUNIT = LSAME( DIAG, 'N' ) +* +* Test the input parameters. +* + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -2 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -3 + ELSE IF( .NOT.LSAME( NORMIN, 'Y' ) .AND. .NOT. + $ LSAME( NORMIN, 'N' ) ) THEN + INFO = -4 + ELSE IF( N.LT.0 ) THEN + INFO = -5 + ELSE IF( KD.LT.0 ) THEN + INFO = -6 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZLATBS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine machine dependent parameters to control overflow. +* + SMLNUM = DLAMCH( 'Safe minimum' ) + BIGNUM = ONE / SMLNUM + CALL DLABAD( SMLNUM, BIGNUM ) + SMLNUM = SMLNUM / DLAMCH( 'Precision' ) + BIGNUM = ONE / SMLNUM + SCALE = ONE +* + IF( LSAME( NORMIN, 'N' ) ) THEN +* +* Compute the 1-norm of each column, not including the diagonal. +* + IF( UPPER ) THEN +* +* A is upper triangular. +* + DO 10 J = 1, N + JLEN = MIN( KD, J-1 ) + CNORM( J ) = DZASUM( JLEN, AB( KD+1-JLEN, J ), 1 ) + 10 CONTINUE + ELSE +* +* A is lower triangular. +* + DO 20 J = 1, N + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.0 ) THEN + CNORM( J ) = DZASUM( JLEN, AB( 2, J ), 1 ) + ELSE + CNORM( J ) = ZERO + END IF + 20 CONTINUE + END IF + END IF +* +* Scale the column norms by TSCAL if the maximum element in CNORM is +* greater than BIGNUM/2. +* + IMAX = IDAMAX( N, CNORM, 1 ) + TMAX = CNORM( IMAX ) + IF( TMAX.LE.BIGNUM*HALF ) THEN + TSCAL = ONE + ELSE + TSCAL = HALF / ( SMLNUM*TMAX ) + CALL DSCAL( N, TSCAL, CNORM, 1 ) + END IF +* +* Compute a bound on the computed solution vector to see if the +* Level 2 BLAS routine ZTBSV can be used. +* + XMAX = ZERO + DO 30 J = 1, N + XMAX = MAX( XMAX, CABS2( X( J ) ) ) + 30 CONTINUE + XBND = XMAX + IF( NOTRAN ) THEN +* +* Compute the growth in A * x = b. +* + IF( UPPER ) THEN + JFIRST = N + JLAST = 1 + JINC = -1 + MAIND = KD + 1 + ELSE + JFIRST = 1 + JLAST = N + JINC = 1 + MAIND = 1 + END IF +* + IF( TSCAL.NE.ONE ) THEN + GROW = ZERO + GO TO 60 + END IF +* + IF( NOUNIT ) THEN +* +* A is non-unit triangular. +* +* Compute GROW = 1/G(j) and XBND = 1/M(j). +* Initially, G(0) = max{x(i), i=1,...,n}. +* + GROW = HALF / MAX( XBND, SMLNUM ) + XBND = GROW + DO 40 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 60 +* + TJJS = AB( MAIND, J ) + TJJ = CABS1( TJJS ) +* + IF( TJJ.GE.SMLNUM ) THEN +* +* M(j) = G(j-1) / abs(A(j,j)) +* + XBND = MIN( XBND, MIN( ONE, TJJ )*GROW ) + ELSE +* +* M(j) could overflow, set XBND to 0. +* + XBND = ZERO + END IF +* + IF( TJJ+CNORM( J ).GE.SMLNUM ) THEN +* +* G(j) = G(j-1)*( 1 + CNORM(j) / abs(A(j,j)) ) +* + GROW = GROW*( TJJ / ( TJJ+CNORM( J ) ) ) + ELSE +* +* G(j) could overflow, set GROW to 0. +* + GROW = ZERO + END IF + 40 CONTINUE + GROW = XBND + ELSE +* +* A is unit triangular. +* +* Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. +* + GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) ) + DO 50 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 60 +* +* G(j) = G(j-1)*( 1 + CNORM(j) ) +* + GROW = GROW*( ONE / ( ONE+CNORM( J ) ) ) + 50 CONTINUE + END IF + 60 CONTINUE +* + ELSE +* +* Compute the growth in A**T * x = b or A**H * x = b. +* + IF( UPPER ) THEN + JFIRST = 1 + JLAST = N + JINC = 1 + MAIND = KD + 1 + ELSE + JFIRST = N + JLAST = 1 + JINC = -1 + MAIND = 1 + END IF +* + IF( TSCAL.NE.ONE ) THEN + GROW = ZERO + GO TO 90 + END IF +* + IF( NOUNIT ) THEN +* +* A is non-unit triangular. +* +* Compute GROW = 1/G(j) and XBND = 1/M(j). +* Initially, M(0) = max{x(i), i=1,...,n}. +* + GROW = HALF / MAX( XBND, SMLNUM ) + XBND = GROW + DO 70 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 90 +* +* G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) ) +* + XJ = ONE + CNORM( J ) + GROW = MIN( GROW, XBND / XJ ) +* + TJJS = AB( MAIND, J ) + TJJ = CABS1( TJJS ) +* + IF( TJJ.GE.SMLNUM ) THEN +* +* M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j)) +* + IF( XJ.GT.TJJ ) + $ XBND = XBND*( TJJ / XJ ) + ELSE +* +* M(j) could overflow, set XBND to 0. +* + XBND = ZERO + END IF + 70 CONTINUE + GROW = MIN( GROW, XBND ) + ELSE +* +* A is unit triangular. +* +* Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. +* + GROW = MIN( ONE, HALF / MAX( XBND, SMLNUM ) ) + DO 80 J = JFIRST, JLAST, JINC +* +* Exit the loop if the growth factor is too small. +* + IF( GROW.LE.SMLNUM ) + $ GO TO 90 +* +* G(j) = ( 1 + CNORM(j) )*G(j-1) +* + XJ = ONE + CNORM( J ) + GROW = GROW / XJ + 80 CONTINUE + END IF + 90 CONTINUE + END IF +* + IF( ( GROW*TSCAL ).GT.SMLNUM ) THEN +* +* Use the Level 2 BLAS solve if the reciprocal of the bound on +* elements of X is not too small. +* + CALL ZTBSV( UPLO, TRANS, DIAG, N, KD, AB, LDAB, X, 1 ) + ELSE +* +* Use a Level 1 BLAS solve, scaling intermediate results. +* + IF( XMAX.GT.BIGNUM*HALF ) THEN +* +* Scale X so that its components are less than or equal to +* BIGNUM in absolute value. +* + SCALE = ( BIGNUM*HALF ) / XMAX + CALL ZDSCAL( N, SCALE, X, 1 ) + XMAX = BIGNUM + ELSE + XMAX = XMAX*TWO + END IF +* + IF( NOTRAN ) THEN +* +* Solve A * x = b +* + DO 120 J = JFIRST, JLAST, JINC +* +* Compute x(j) = b(j) / A(j,j), scaling x if necessary. +* + XJ = CABS1( X( J ) ) + IF( NOUNIT ) THEN + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + IF( TSCAL.EQ.ONE ) + $ GO TO 110 + END IF + TJJ = CABS1( TJJS ) + IF( TJJ.GT.SMLNUM ) THEN +* +* abs(A(j,j)) > SMLNUM: +* + IF( TJJ.LT.ONE ) THEN + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by 1/b(j). +* + REC = ONE / XJ + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + XJ = CABS1( X( J ) ) + ELSE IF( TJJ.GT.ZERO ) THEN +* +* 0 < abs(A(j,j)) <= SMLNUM: +* + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM +* to avoid overflow when dividing by A(j,j). +* + REC = ( TJJ*BIGNUM ) / XJ + IF( CNORM( J ).GT.ONE ) THEN +* +* Scale by 1/CNORM(j) to avoid overflow when +* multiplying x(j) times column j. +* + REC = REC / CNORM( J ) + END IF + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + XJ = CABS1( X( J ) ) + ELSE +* +* A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and +* scale = 0, and compute a solution to A*x = 0. +* + DO 100 I = 1, N + X( I ) = ZERO + 100 CONTINUE + X( J ) = ONE + XJ = ONE + SCALE = ZERO + XMAX = ZERO + END IF + 110 CONTINUE +* +* Scale x if necessary to avoid overflow when adding a +* multiple of column j of A. +* + IF( XJ.GT.ONE ) THEN + REC = ONE / XJ + IF( CNORM( J ).GT.( BIGNUM-XMAX )*REC ) THEN +* +* Scale x by 1/(2*abs(x(j))). +* + REC = REC*HALF + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + END IF + ELSE IF( XJ*CNORM( J ).GT.( BIGNUM-XMAX ) ) THEN +* +* Scale x by 1/2. +* + CALL ZDSCAL( N, HALF, X, 1 ) + SCALE = SCALE*HALF + END IF +* + IF( UPPER ) THEN + IF( J.GT.1 ) THEN +* +* Compute the update +* x(max(1,j-kd):j-1) := x(max(1,j-kd):j-1) - +* x(j)* A(max(1,j-kd):j-1,j) +* + JLEN = MIN( KD, J-1 ) + CALL ZAXPY( JLEN, -X( J )*TSCAL, + $ AB( KD+1-JLEN, J ), 1, X( J-JLEN ), 1 ) + I = IZAMAX( J-1, X, 1 ) + XMAX = CABS1( X( I ) ) + END IF + ELSE IF( J.LT.N ) THEN +* +* Compute the update +* x(j+1:min(j+kd,n)) := x(j+1:min(j+kd,n)) - +* x(j) * A(j+1:min(j+kd,n),j) +* + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.0 ) + $ CALL ZAXPY( JLEN, -X( J )*TSCAL, AB( 2, J ), 1, + $ X( J+1 ), 1 ) + I = J + IZAMAX( N-J, X( J+1 ), 1 ) + XMAX = CABS1( X( I ) ) + END IF + 120 CONTINUE +* + ELSE IF( LSAME( TRANS, 'T' ) ) THEN +* +* Solve A**T * x = b +* + DO 170 J = JFIRST, JLAST, JINC +* +* Compute x(j) = b(j) - sum A(k,j)*x(k). +* k<>j +* + XJ = CABS1( X( J ) ) + USCAL = TSCAL + REC = ONE / MAX( XMAX, ONE ) + IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN +* +* If x(j) could overflow, scale x by 1/(2*XMAX). +* + REC = REC*HALF + IF( NOUNIT ) THEN + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + END IF + TJJ = CABS1( TJJS ) + IF( TJJ.GT.ONE ) THEN +* +* Divide by A(j,j) when scaling x if A(j,j) > 1. +* + REC = MIN( ONE, REC*TJJ ) + USCAL = ZLADIV( USCAL, TJJS ) + END IF + IF( REC.LT.ONE ) THEN + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF +* + CSUMJ = ZERO + IF( USCAL.EQ.DCMPLX( ONE ) ) THEN +* +* If the scaling needed for A in the dot product is 1, +* call ZDOTU to perform the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + CSUMJ = ZDOTU( JLEN, AB( KD+1-JLEN, J ), 1, + $ X( J-JLEN ), 1 ) + ELSE + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.1 ) + $ CSUMJ = ZDOTU( JLEN, AB( 2, J ), 1, X( J+1 ), + $ 1 ) + END IF + ELSE +* +* Otherwise, use in-line code for the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + DO 130 I = 1, JLEN + CSUMJ = CSUMJ + ( AB( KD+I-JLEN, J )*USCAL )* + $ X( J-JLEN-1+I ) + 130 CONTINUE + ELSE + JLEN = MIN( KD, N-J ) + DO 140 I = 1, JLEN + CSUMJ = CSUMJ + ( AB( I+1, J )*USCAL )*X( J+I ) + 140 CONTINUE + END IF + END IF +* + IF( USCAL.EQ.DCMPLX( TSCAL ) ) THEN +* +* Compute x(j) := ( x(j) - CSUMJ ) / A(j,j) if 1/A(j,j) +* was not used to scale the dotproduct. +* + X( J ) = X( J ) - CSUMJ + XJ = CABS1( X( J ) ) + IF( NOUNIT ) THEN +* +* Compute x(j) = x(j) / A(j,j), scaling if necessary. +* + TJJS = AB( MAIND, J )*TSCAL + ELSE + TJJS = TSCAL + IF( TSCAL.EQ.ONE ) + $ GO TO 160 + END IF + TJJ = CABS1( TJJS ) + IF( TJJ.GT.SMLNUM ) THEN +* +* abs(A(j,j)) > SMLNUM: +* + IF( TJJ.LT.ONE ) THEN + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale X by 1/abs(x(j)). +* + REC = ONE / XJ + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + ELSE IF( TJJ.GT.ZERO ) THEN +* +* 0 < abs(A(j,j)) <= SMLNUM: +* + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. +* + REC = ( TJJ*BIGNUM ) / XJ + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + ELSE +* +* A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and +* scale = 0 and compute a solution to A**T *x = 0. +* + DO 150 I = 1, N + X( I ) = ZERO + 150 CONTINUE + X( J ) = ONE + SCALE = ZERO + XMAX = ZERO + END IF + 160 CONTINUE + ELSE +* +* Compute x(j) := x(j) / A(j,j) - CSUMJ if the dot +* product has already been divided by 1/A(j,j). +* + X( J ) = ZLADIV( X( J ), TJJS ) - CSUMJ + END IF + XMAX = MAX( XMAX, CABS1( X( J ) ) ) + 170 CONTINUE +* + ELSE +* +* Solve A**H * x = b +* + DO 220 J = JFIRST, JLAST, JINC +* +* Compute x(j) = b(j) - sum A(k,j)*x(k). +* k<>j +* + XJ = CABS1( X( J ) ) + USCAL = TSCAL + REC = ONE / MAX( XMAX, ONE ) + IF( CNORM( J ).GT.( BIGNUM-XJ )*REC ) THEN +* +* If x(j) could overflow, scale x by 1/(2*XMAX). +* + REC = REC*HALF + IF( NOUNIT ) THEN + TJJS = DCONJG( AB( MAIND, J ) )*TSCAL + ELSE + TJJS = TSCAL + END IF + TJJ = CABS1( TJJS ) + IF( TJJ.GT.ONE ) THEN +* +* Divide by A(j,j) when scaling x if A(j,j) > 1. +* + REC = MIN( ONE, REC*TJJ ) + USCAL = ZLADIV( USCAL, TJJS ) + END IF + IF( REC.LT.ONE ) THEN + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF +* + CSUMJ = ZERO + IF( USCAL.EQ.DCMPLX( ONE ) ) THEN +* +* If the scaling needed for A in the dot product is 1, +* call ZDOTC to perform the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + CSUMJ = ZDOTC( JLEN, AB( KD+1-JLEN, J ), 1, + $ X( J-JLEN ), 1 ) + ELSE + JLEN = MIN( KD, N-J ) + IF( JLEN.GT.1 ) + $ CSUMJ = ZDOTC( JLEN, AB( 2, J ), 1, X( J+1 ), + $ 1 ) + END IF + ELSE +* +* Otherwise, use in-line code for the dot product. +* + IF( UPPER ) THEN + JLEN = MIN( KD, J-1 ) + DO 180 I = 1, JLEN + CSUMJ = CSUMJ + ( DCONJG( AB( KD+I-JLEN, J ) )* + $ USCAL )*X( J-JLEN-1+I ) + 180 CONTINUE + ELSE + JLEN = MIN( KD, N-J ) + DO 190 I = 1, JLEN + CSUMJ = CSUMJ + ( DCONJG( AB( I+1, J ) )*USCAL ) + $ *X( J+I ) + 190 CONTINUE + END IF + END IF +* + IF( USCAL.EQ.DCMPLX( TSCAL ) ) THEN +* +* Compute x(j) := ( x(j) - CSUMJ ) / A(j,j) if 1/A(j,j) +* was not used to scale the dotproduct. +* + X( J ) = X( J ) - CSUMJ + XJ = CABS1( X( J ) ) + IF( NOUNIT ) THEN +* +* Compute x(j) = x(j) / A(j,j), scaling if necessary. +* + TJJS = DCONJG( AB( MAIND, J ) )*TSCAL + ELSE + TJJS = TSCAL + IF( TSCAL.EQ.ONE ) + $ GO TO 210 + END IF + TJJ = CABS1( TJJS ) + IF( TJJ.GT.SMLNUM ) THEN +* +* abs(A(j,j)) > SMLNUM: +* + IF( TJJ.LT.ONE ) THEN + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale X by 1/abs(x(j)). +* + REC = ONE / XJ + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + ELSE IF( TJJ.GT.ZERO ) THEN +* +* 0 < abs(A(j,j)) <= SMLNUM: +* + IF( XJ.GT.TJJ*BIGNUM ) THEN +* +* Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. +* + REC = ( TJJ*BIGNUM ) / XJ + CALL ZDSCAL( N, REC, X, 1 ) + SCALE = SCALE*REC + XMAX = XMAX*REC + END IF + X( J ) = ZLADIV( X( J ), TJJS ) + ELSE +* +* A(j,j) = 0: Set x(1:n) = 0, x(j) = 1, and +* scale = 0 and compute a solution to A**H *x = 0. +* + DO 200 I = 1, N + X( I ) = ZERO + 200 CONTINUE + X( J ) = ONE + SCALE = ZERO + XMAX = ZERO + END IF + 210 CONTINUE + ELSE +* +* Compute x(j) := x(j) / A(j,j) - CSUMJ if the dot +* product has already been divided by 1/A(j,j). +* + X( J ) = ZLADIV( X( J ), TJJS ) - CSUMJ + END IF + XMAX = MAX( XMAX, CABS1( X( J ) ) ) + 220 CONTINUE + END IF + SCALE = SCALE / TSCAL + END IF +* +* Scale the column norms by 1/TSCAL for return. +* + IF( TSCAL.NE.ONE ) THEN + CALL DSCAL( N, ONE / TSCAL, CNORM, 1 ) + END IF +* + RETURN +* +* End of ZLATBS +* + END diff --git a/libcruft/lapack/zpbcon.f b/libcruft/lapack/zpbcon.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpbcon.f @@ -0,0 +1,194 @@ + SUBROUTINE ZPBCON( UPLO, N, KD, AB, LDAB, ANORM, RCOND, WORK, + $ RWORK, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N + DOUBLE PRECISION ANORM, RCOND +* .. +* .. Array Arguments .. + DOUBLE PRECISION RWORK( * ) + COMPLEX*16 AB( LDAB, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* ZPBCON estimates the reciprocal of the condition number (in the +* 1-norm) of a complex Hermitian positive definite band matrix using +* the Cholesky factorization A = U**H*U or A = L*L**H computed by +* ZPBTRF. +* +* An estimate is obtained for norm(inv(A)), and the reciprocal of the +* condition number is computed as RCOND = 1 / (ANORM * norm(inv(A))). +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangular factor stored in AB; +* = 'L': Lower triangular factor stored in AB. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of sub-diagonals if UPLO = 'L'. KD >= 0. +* +* AB (input) COMPLEX*16 array, dimension (LDAB,N) +* The triangular factor U or L from the Cholesky factorization +* A = U**H*U or A = L*L**H of the band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of U or L is +* stored in the j-th column of the array AB as follows: +* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j; +* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* ANORM (input) DOUBLE PRECISION +* The 1-norm (or infinity-norm) of the Hermitian band matrix A. +* +* RCOND (output) DOUBLE PRECISION +* The reciprocal of the condition number of the matrix A, +* computed as RCOND = 1/(ANORM * AINVNM), where AINVNM is an +* estimate of the 1-norm of inv(A) computed in this routine. +* +* WORK (workspace) COMPLEX*16 array, dimension (2*N) +* +* RWORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + CHARACTER NORMIN + INTEGER IX, KASE + DOUBLE PRECISION AINVNM, SCALE, SCALEL, SCALEU, SMLNUM + COMPLEX*16 ZDUM +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IZAMAX + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, IZAMAX, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZDRSCL, ZLACON, ZLATBS +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, DIMAG +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) + ABS( DIMAG( ZDUM ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + ELSE IF( ANORM.LT.ZERO ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPBCON', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + RCOND = ZERO + IF( N.EQ.0 ) THEN + RCOND = ONE + RETURN + ELSE IF( ANORM.EQ.ZERO ) THEN + RETURN + END IF +* + SMLNUM = DLAMCH( 'Safe minimum' ) +* +* Estimate the 1-norm of the inverse. +* + KASE = 0 + NORMIN = 'N' + 10 CONTINUE + CALL ZLACON( N, WORK( N+1 ), WORK, AINVNM, KASE ) + IF( KASE.NE.0 ) THEN + IF( UPPER ) THEN +* +* Multiply by inv(U'). +* + CALL ZLATBS( 'Upper', 'Conjugate transpose', 'Non-unit', + $ NORMIN, N, KD, AB, LDAB, WORK, SCALEL, RWORK, + $ INFO ) + NORMIN = 'Y' +* +* Multiply by inv(U). +* + CALL ZLATBS( 'Upper', 'No transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEU, RWORK, INFO ) + ELSE +* +* Multiply by inv(L). +* + CALL ZLATBS( 'Lower', 'No transpose', 'Non-unit', NORMIN, N, + $ KD, AB, LDAB, WORK, SCALEL, RWORK, INFO ) + NORMIN = 'Y' +* +* Multiply by inv(L'). +* + CALL ZLATBS( 'Lower', 'Conjugate transpose', 'Non-unit', + $ NORMIN, N, KD, AB, LDAB, WORK, SCALEU, RWORK, + $ INFO ) + END IF +* +* Multiply by 1/SCALE if doing so will not cause overflow. +* + SCALE = SCALEL*SCALEU + IF( SCALE.NE.ONE ) THEN + IX = IZAMAX( N, WORK, 1 ) + IF( SCALE.LT.CABS1( WORK( IX ) )*SMLNUM .OR. SCALE.EQ.ZERO ) + $ GO TO 20 + CALL ZDRSCL( N, SCALE, WORK, 1 ) + END IF + GO TO 10 + END IF +* +* Compute the estimate of the reciprocal condition number. +* + IF( AINVNM.NE.ZERO ) + $ RCOND = ( ONE / AINVNM ) / ANORM +* + 20 CONTINUE +* + RETURN +* +* End of ZPBCON +* + END diff --git a/libcruft/lapack/zpbtf2.f b/libcruft/lapack/zpbtf2.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpbtf2.f @@ -0,0 +1,201 @@ + SUBROUTINE ZPBTF2( UPLO, N, KD, AB, LDAB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N +* .. +* .. Array Arguments .. + COMPLEX*16 AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* ZPBTF2 computes the Cholesky factorization of a complex Hermitian +* positive definite band matrix A. +* +* The factorization has the form +* A = U' * U , if UPLO = 'U', or +* A = L * L', if UPLO = 'L', +* where U is an upper triangular matrix, U' is the conjugate transpose +* of U, and L is lower triangular. +* +* This is the unblocked version of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* Hermitian matrix A is stored: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of super-diagonals of the matrix A if UPLO = 'U', +* or the number of sub-diagonals if UPLO = 'L'. KD >= 0. +* +* AB (input/output) COMPLEX*16 array, dimension (LDAB,N) +* On entry, the upper or lower triangle of the Hermitian band +* matrix A, stored in the first KD+1 rows of the array. The +* j-th column of A is stored in the j-th column of the array AB +* as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* On exit, if INFO = 0, the triangular factor U or L from the +* Cholesky factorization A = U'*U or A = L*L' of the band +* matrix A, in the same storage format as A. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, the leading minor of order k is not +* positive definite, and the factorization could not be +* completed. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* N = 6, KD = 2, and UPLO = 'U': +* +* On entry: On exit: +* +* * * a13 a24 a35 a46 * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* +* Similarly, if UPLO = 'L' the format of A is as follows: +* +* On entry: On exit: +* +* a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66 +* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 * +* a31 a42 a53 a64 * * l31 l42 l53 l64 * * +* +* Array elements marked * are not used by the routine. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J, KLD, KN + DOUBLE PRECISION AJJ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZDSCAL, ZHER, ZLACGV +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPBTF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + KLD = MAX( 1, LDAB-1 ) +* + IF( UPPER ) THEN +* +* Compute the Cholesky factorization A = U'*U. +* + DO 10 J = 1, N +* +* Compute U(J,J) and test for non-positive-definiteness. +* + AJJ = DBLE( AB( KD+1, J ) ) + IF( AJJ.LE.ZERO ) THEN + AB( KD+1, J ) = AJJ + GO TO 30 + END IF + AJJ = SQRT( AJJ ) + AB( KD+1, J ) = AJJ +* +* Compute elements J+1:J+KN of row J and update the +* trailing submatrix within the band. +* + KN = MIN( KD, N-J ) + IF( KN.GT.0 ) THEN + CALL ZDSCAL( KN, ONE / AJJ, AB( KD, J+1 ), KLD ) + CALL ZLACGV( KN, AB( KD, J+1 ), KLD ) + CALL ZHER( 'Upper', KN, -ONE, AB( KD, J+1 ), KLD, + $ AB( KD+1, J+1 ), KLD ) + CALL ZLACGV( KN, AB( KD, J+1 ), KLD ) + END IF + 10 CONTINUE + ELSE +* +* Compute the Cholesky factorization A = L*L'. +* + DO 20 J = 1, N +* +* Compute L(J,J) and test for non-positive-definiteness. +* + AJJ = DBLE( AB( 1, J ) ) + IF( AJJ.LE.ZERO ) THEN + AB( 1, J ) = AJJ + GO TO 30 + END IF + AJJ = SQRT( AJJ ) + AB( 1, J ) = AJJ +* +* Compute elements J+1:J+KN of column J and update the +* trailing submatrix within the band. +* + KN = MIN( KD, N-J ) + IF( KN.GT.0 ) THEN + CALL ZDSCAL( KN, ONE / AJJ, AB( 2, J ), 1 ) + CALL ZHER( 'Lower', KN, -ONE, AB( 2, J ), 1, + $ AB( 1, J+1 ), KLD ) + END IF + 20 CONTINUE + END IF + RETURN +* + 30 CONTINUE + INFO = J + RETURN +* +* End of ZPBTF2 +* + END diff --git a/libcruft/lapack/zpbtrf.f b/libcruft/lapack/zpbtrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpbtrf.f @@ -0,0 +1,372 @@ + SUBROUTINE ZPBTRF( UPLO, N, KD, AB, LDAB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, N +* .. +* .. Array Arguments .. + COMPLEX*16 AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* ZPBTRF computes the Cholesky factorization of a complex Hermitian +* positive definite band matrix A. +* +* The factorization has the form +* A = U**H * U, if UPLO = 'U', or +* A = L * L**H, if UPLO = 'L', +* where U is an upper triangular matrix and L is lower triangular. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of subdiagonals if UPLO = 'L'. KD >= 0. +* +* AB (input/output) COMPLEX*16 array, dimension (LDAB,N) +* On entry, the upper or lower triangle of the Hermitian band +* matrix A, stored in the first KD+1 rows of the array. The +* j-th column of A is stored in the j-th column of the array AB +* as follows: +* if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j; +* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd). +* +* On exit, if INFO = 0, the triangular factor U or L from the +* Cholesky factorization A = U**H*U or A = L*L**H of the band +* matrix A, in the same storage format as A. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite, and the factorization could not be +* completed. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* N = 6, KD = 2, and UPLO = 'U': +* +* On entry: On exit: +* +* * * a13 a24 a35 a46 * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* +* Similarly, if UPLO = 'L' the format of A is as follows: +* +* On entry: On exit: +* +* a11 a22 a33 a44 a55 a66 l11 l22 l33 l44 l55 l66 +* a21 a32 a43 a54 a65 * l21 l32 l43 l54 l65 * +* a31 a42 a53 a64 * * l31 l42 l53 l64 * * +* +* Array elements marked * are not used by the routine. +* +* Contributed by +* Peter Mayes and Giuseppe Radicati, IBM ECSEC, Rome, March 23, 1989 +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) + COMPLEX*16 CONE + PARAMETER ( CONE = ( 1.0D+0, 0.0D+0 ) ) + INTEGER NBMAX, LDWORK + PARAMETER ( NBMAX = 32, LDWORK = NBMAX+1 ) +* .. +* .. Local Scalars .. + INTEGER I, I2, I3, IB, II, J, JJ, NB +* .. +* .. Local Arrays .. + COMPLEX*16 WORK( LDWORK, NBMAX ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGEMM, ZHERK, ZPBTF2, ZPOTF2, ZTRSM +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.LSAME( UPLO, 'U' ) ) .AND. + $ ( .NOT.LSAME( UPLO, 'L' ) ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPBTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment +* + NB = ILAENV( 1, 'ZPBTRF', UPLO, N, KD, -1, -1 ) +* +* The block size must not exceed the semi-bandwidth KD, and must not +* exceed the limit set by the size of the local array WORK. +* + NB = MIN( NB, NBMAX ) +* + IF( NB.LE.1 .OR. NB.GT.KD ) THEN +* +* Use unblocked code +* + CALL ZPBTF2( UPLO, N, KD, AB, LDAB, INFO ) + ELSE +* +* Use blocked code +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Compute the Cholesky factorization of a Hermitian band +* matrix, given the upper triangle of the matrix in band +* storage. +* +* Zero the upper triangle of the work array. +* + DO 20 J = 1, NB + DO 10 I = 1, J - 1 + WORK( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* Process the band matrix one diagonal block at a time. +* + DO 70 I = 1, N, NB + IB = MIN( NB, N-I+1 ) +* +* Factorize the diagonal block +* + CALL ZPOTF2( UPLO, IB, AB( KD+1, I ), LDAB-1, II ) + IF( II.NE.0 ) THEN + INFO = I + II - 1 + GO TO 150 + END IF + IF( I+IB.LE.N ) THEN +* +* Update the relevant part of the trailing submatrix. +* If A11 denotes the diagonal block which has just been +* factorized, then we need to update the remaining +* blocks in the diagram: +* +* A11 A12 A13 +* A22 A23 +* A33 +* +* The numbers of rows and columns in the partitioning +* are IB, I2, I3 respectively. The blocks A12, A22 and +* A23 are empty if IB = KD. The upper triangle of A13 +* lies outside the band. +* + I2 = MIN( KD-IB, N-I-IB+1 ) + I3 = MIN( IB, N-I-KD+1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A12 +* + CALL ZTRSM( 'Left', 'Upper', 'Conjugate transpose', + $ 'Non-unit', IB, I2, CONE, + $ AB( KD+1, I ), LDAB-1, + $ AB( KD+1-IB, I+IB ), LDAB-1 ) +* +* Update A22 +* + CALL ZHERK( 'Upper', 'Conjugate transpose', I2, IB, + $ -ONE, AB( KD+1-IB, I+IB ), LDAB-1, ONE, + $ AB( KD+1, I+IB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Copy the lower triangle of A13 into the work array. +* + DO 40 JJ = 1, I3 + DO 30 II = JJ, IB + WORK( II, JJ ) = AB( II-JJ+1, JJ+I+KD-1 ) + 30 CONTINUE + 40 CONTINUE +* +* Update A13 (in the work array). +* + CALL ZTRSM( 'Left', 'Upper', 'Conjugate transpose', + $ 'Non-unit', IB, I3, CONE, + $ AB( KD+1, I ), LDAB-1, WORK, LDWORK ) +* +* Update A23 +* + IF( I2.GT.0 ) + $ CALL ZGEMM( 'Conjugate transpose', + $ 'No transpose', I2, I3, IB, -CONE, + $ AB( KD+1-IB, I+IB ), LDAB-1, WORK, + $ LDWORK, CONE, AB( 1+IB, I+KD ), + $ LDAB-1 ) +* +* Update A33 +* + CALL ZHERK( 'Upper', 'Conjugate transpose', I3, IB, + $ -ONE, WORK, LDWORK, ONE, + $ AB( KD+1, I+KD ), LDAB-1 ) +* +* Copy the lower triangle of A13 back into place. +* + DO 60 JJ = 1, I3 + DO 50 II = JJ, IB + AB( II-JJ+1, JJ+I+KD-1 ) = WORK( II, JJ ) + 50 CONTINUE + 60 CONTINUE + END IF + END IF + 70 CONTINUE + ELSE +* +* Compute the Cholesky factorization of a Hermitian band +* matrix, given the lower triangle of the matrix in band +* storage. +* +* Zero the lower triangle of the work array. +* + DO 90 J = 1, NB + DO 80 I = J + 1, NB + WORK( I, J ) = ZERO + 80 CONTINUE + 90 CONTINUE +* +* Process the band matrix one diagonal block at a time. +* + DO 140 I = 1, N, NB + IB = MIN( NB, N-I+1 ) +* +* Factorize the diagonal block +* + CALL ZPOTF2( UPLO, IB, AB( 1, I ), LDAB-1, II ) + IF( II.NE.0 ) THEN + INFO = I + II - 1 + GO TO 150 + END IF + IF( I+IB.LE.N ) THEN +* +* Update the relevant part of the trailing submatrix. +* If A11 denotes the diagonal block which has just been +* factorized, then we need to update the remaining +* blocks in the diagram: +* +* A11 +* A21 A22 +* A31 A32 A33 +* +* The numbers of rows and columns in the partitioning +* are IB, I2, I3 respectively. The blocks A21, A22 and +* A32 are empty if IB = KD. The lower triangle of A31 +* lies outside the band. +* + I2 = MIN( KD-IB, N-I-IB+1 ) + I3 = MIN( IB, N-I-KD+1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A21 +* + CALL ZTRSM( 'Right', 'Lower', + $ 'Conjugate transpose', 'Non-unit', I2, + $ IB, CONE, AB( 1, I ), LDAB-1, + $ AB( 1+IB, I ), LDAB-1 ) +* +* Update A22 +* + CALL ZHERK( 'Lower', 'No transpose', I2, IB, -ONE, + $ AB( 1+IB, I ), LDAB-1, ONE, + $ AB( 1, I+IB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Copy the upper triangle of A31 into the work array. +* + DO 110 JJ = 1, IB + DO 100 II = 1, MIN( JJ, I3 ) + WORK( II, JJ ) = AB( KD+1-JJ+II, JJ+I-1 ) + 100 CONTINUE + 110 CONTINUE +* +* Update A31 (in the work array). +* + CALL ZTRSM( 'Right', 'Lower', + $ 'Conjugate transpose', 'Non-unit', I3, + $ IB, CONE, AB( 1, I ), LDAB-1, WORK, + $ LDWORK ) +* +* Update A32 +* + IF( I2.GT.0 ) + $ CALL ZGEMM( 'No transpose', + $ 'Conjugate transpose', I3, I2, IB, + $ -CONE, WORK, LDWORK, AB( 1+IB, I ), + $ LDAB-1, CONE, AB( 1+KD-IB, I+IB ), + $ LDAB-1 ) +* +* Update A33 +* + CALL ZHERK( 'Lower', 'No transpose', I3, IB, -ONE, + $ WORK, LDWORK, ONE, AB( 1, I+KD ), + $ LDAB-1 ) +* +* Copy the upper triangle of A31 back into place. +* + DO 130 JJ = 1, IB + DO 120 II = 1, MIN( JJ, I3 ) + AB( KD+1-JJ+II, JJ+I-1 ) = WORK( II, JJ ) + 120 CONTINUE + 130 CONTINUE + END IF + END IF + 140 CONTINUE + END IF + END IF + RETURN +* + 150 CONTINUE + RETURN +* +* End of ZPBTRF +* + END diff --git a/libcruft/lapack/zpbtrs.f b/libcruft/lapack/zpbtrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpbtrs.f @@ -0,0 +1,146 @@ + SUBROUTINE ZPBTRS( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, KD, LDAB, LDB, N, NRHS +* .. +* .. Array Arguments .. + COMPLEX*16 AB( LDAB, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZPBTRS solves a system of linear equations A*X = B with a Hermitian +* positive definite band matrix A using the Cholesky factorization +* A = U**H*U or A = L*L**H computed by ZPBTRF. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangular factor stored in AB; +* = 'L': Lower triangular factor stored in AB. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KD (input) INTEGER +* The number of superdiagonals of the matrix A if UPLO = 'U', +* or the number of subdiagonals if UPLO = 'L'. KD >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* AB (input) COMPLEX*16 array, dimension (LDAB,N) +* The triangular factor U or L from the Cholesky factorization +* A = U**H*U or A = L*L**H of the band matrix A, stored in the +* first KD+1 rows of the array. The j-th column of U or L is +* stored in the j-th column of the array AB as follows: +* if UPLO ='U', AB(kd+1+i-j,j) = U(i,j) for max(1,j-kd)<=i<=j; +* if UPLO ='L', AB(1+i-j,j) = L(i,j) for j<=i<=min(n,j+kd). +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= KD+1. +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZTBSV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KD.LT.0 ) THEN + INFO = -3 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KD+1 ) THEN + INFO = -6 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPBTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Solve A*X = B where A = U'*U. +* + DO 10 J = 1, NRHS +* +* Solve U'*X = B, overwriting B with X. +* + CALL ZTBSV( 'Upper', 'Conjugate transpose', 'Non-unit', N, + $ KD, AB, LDAB, B( 1, J ), 1 ) +* +* Solve U*X = B, overwriting B with X. +* + CALL ZTBSV( 'Upper', 'No transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) + 10 CONTINUE + ELSE +* +* Solve A*X = B where A = L*L'. +* + DO 20 J = 1, NRHS +* +* Solve L*X = B, overwriting B with X. +* + CALL ZTBSV( 'Lower', 'No transpose', 'Non-unit', N, KD, AB, + $ LDAB, B( 1, J ), 1 ) +* +* Solve L'*X = B, overwriting B with X. +* + CALL ZTBSV( 'Lower', 'Conjugate transpose', 'Non-unit', N, + $ KD, AB, LDAB, B( 1, J ), 1 ) + 20 CONTINUE + END IF +* + RETURN +* +* End of ZPBTRS +* + END diff --git a/libcruft/lapack/zptsv.f b/libcruft/lapack/zptsv.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zptsv.f @@ -0,0 +1,101 @@ + SUBROUTINE ZPTSV( N, NRHS, D, E, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 25, 1997 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) + COMPLEX*16 B( LDB, * ), E( * ) +* .. +* +* Purpose +* ======= +* +* ZPTSV computes the solution to a complex system of linear equations +* A*X = B, where A is an N-by-N Hermitian positive definite tridiagonal +* matrix, and X and B are N-by-NRHS matrices. +* +* A is factored as A = L*D*L**H, and the factored form of A is then +* used to solve the system of equations. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. On exit, the n diagonal elements of the diagonal matrix +* D from the factorization A = L*D*L**H. +* +* E (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix A. On exit, the (n-1) subdiagonal elements of the +* unit bidiagonal factor L from the L*D*L**H factorization of +* A. E can also be regarded as the superdiagonal of the unit +* bidiagonal factor U from the U**H*D*U factorization of A. +* +* B (input/output) COMPLEX*16 array, dimension (LDB,N) +* On entry, the N-by-NRHS right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite, and the solution has not been +* computed. The factorization has not been completed +* unless i = N. +* +* ===================================================================== +* +* .. External Subroutines .. + EXTERNAL XERBLA, ZPTTRF, ZPTTRS +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPTSV ', -INFO ) + RETURN + END IF +* +* Compute the L*D*L' (or U'*D*U) factorization of A. +* + CALL ZPTTRF( N, D, E, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL ZPTTRS( 'Lower', N, NRHS, D, E, B, LDB, INFO ) + END IF + RETURN +* +* End of ZPTSV +* + END diff --git a/libcruft/lapack/zpttrf.f b/libcruft/lapack/zpttrf.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpttrf.f @@ -0,0 +1,169 @@ + SUBROUTINE ZPTTRF( N, D, E, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) + COMPLEX*16 E( * ) +* .. +* +* Purpose +* ======= +* +* ZPTTRF computes the L*D*L' factorization of a complex Hermitian +* positive definite tridiagonal matrix A. The factorization may also +* be regarded as having the form A = U'*D*U. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. On exit, the n diagonal elements of the diagonal matrix +* D from the L*D*L' factorization of A. +* +* E (input/output) COMPLEX*16 array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix A. On exit, the (n-1) subdiagonal elements of the +* unit bidiagonal factor L from the L*D*L' factorization of A. +* E can also be regarded as the superdiagonal of the unit +* bidiagonal factor U from the U'*D*U factorization of A. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, the leading minor of order k is not +* positive definite; if k < N, the factorization could not +* be completed, while if k = N, the factorization was +* completed, but D(N) = 0. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, I4 + DOUBLE PRECISION EII, EIR, F, G +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, DCMPLX, DIMAG, MOD +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'ZPTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Compute the L*D*L' (or U'*D*U) factorization of A. +* + I4 = MOD( N-1, 4 ) + DO 10 I = 1, I4 + IF( D( I ).LE.ZERO ) THEN + INFO = I + GO TO 30 + END IF + EIR = DBLE( E( I ) ) + EII = DIMAG( E( I ) ) + F = EIR / D( I ) + G = EII / D( I ) + E( I ) = DCMPLX( F, G ) + D( I+1 ) = D( I+1 ) - F*EIR - G*EII + 10 CONTINUE +* + DO 20 I = I4 + 1, N - 4, 4 +* +* Drop out of the loop if d(i) <= 0: the matrix is not positive +* definite. +* + IF( D( I ).LE.ZERO ) THEN + INFO = I + GO TO 30 + END IF +* +* Solve for e(i) and d(i+1). +* + EIR = DBLE( E( I ) ) + EII = DIMAG( E( I ) ) + F = EIR / D( I ) + G = EII / D( I ) + E( I ) = DCMPLX( F, G ) + D( I+1 ) = D( I+1 ) - F*EIR - G*EII +* + IF( D( I+1 ).LE.ZERO ) THEN + INFO = I + 1 + GO TO 30 + END IF +* +* Solve for e(i+1) and d(i+2). +* + EIR = DBLE( E( I+1 ) ) + EII = DIMAG( E( I+1 ) ) + F = EIR / D( I+1 ) + G = EII / D( I+1 ) + E( I+1 ) = DCMPLX( F, G ) + D( I+2 ) = D( I+2 ) - F*EIR - G*EII +* + IF( D( I+2 ).LE.ZERO ) THEN + INFO = I + 2 + GO TO 30 + END IF +* +* Solve for e(i+2) and d(i+3). +* + EIR = DBLE( E( I+2 ) ) + EII = DIMAG( E( I+2 ) ) + F = EIR / D( I+2 ) + G = EII / D( I+2 ) + E( I+2 ) = DCMPLX( F, G ) + D( I+3 ) = D( I+3 ) - F*EIR - G*EII +* + IF( D( I+3 ).LE.ZERO ) THEN + INFO = I + 3 + GO TO 30 + END IF +* +* Solve for e(i+3) and d(i+4). +* + EIR = DBLE( E( I+3 ) ) + EII = DIMAG( E( I+3 ) ) + F = EIR / D( I+3 ) + G = EII / D( I+3 ) + E( I+3 ) = DCMPLX( F, G ) + D( I+4 ) = D( I+4 ) - F*EIR - G*EII + 20 CONTINUE +* +* Check d(n) for positive definiteness. +* + IF( D( N ).LE.ZERO ) + $ INFO = N +* + 30 CONTINUE + RETURN +* +* End of ZPTTRF +* + END diff --git a/libcruft/lapack/zpttrs.f b/libcruft/lapack/zpttrs.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zpttrs.f @@ -0,0 +1,136 @@ + SUBROUTINE ZPTTRS( UPLO, N, NRHS, D, E, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) + COMPLEX*16 B( LDB, * ), E( * ) +* .. +* +* Purpose +* ======= +* +* ZPTTRS solves a tridiagonal system of the form +* A * X = B +* using the factorization A = U'*D*U or A = L*D*L' computed by ZPTTRF. +* D is a diagonal matrix specified in the vector D, U (or L) is a unit +* bidiagonal matrix whose superdiagonal (subdiagonal) is specified in +* the vector E, and X and B are N by NRHS matrices. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies the form of the factorization and whether the +* vector E is the superdiagonal of the upper bidiagonal factor +* U or the subdiagonal of the lower bidiagonal factor L. +* = 'U': A = U'*D*U, E is the superdiagonal of U +* = 'L': A = L*D*L', E is the subdiagonal of L +* +* N (input) INTEGER +* The order of the tridiagonal matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the diagonal matrix D from the +* factorization A = U'*D*U or A = L*D*L'. +* +* E (input) COMPLEX*16 array, dimension (N-1) +* If UPLO = 'U', the (n-1) superdiagonal elements of the unit +* bidiagonal factor U from the factorization A = U'*D*U. +* If UPLO = 'L', the (n-1) subdiagonal elements of the unit +* bidiagonal factor L from the factorization A = L*D*L'. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side vectors B for the system of +* linear equations. +* On exit, the solution vectors, X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL UPPER + INTEGER IUPLO, J, JB, NB +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZPTTS2 +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* + INFO = 0 + UPPER = ( UPLO.EQ.'U' .OR. UPLO.EQ.'u' ) + IF( .NOT.UPPER .AND. .NOT.( UPLO.EQ.'L' .OR. UPLO.EQ.'l' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZPTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* +* Determine the number of right-hand sides to solve at a time. +* + IF( NRHS.EQ.1 ) THEN + NB = 1 + ELSE + NB = MAX( 1, ILAENV( 1, 'ZPTTRS', UPLO, N, NRHS, -1, -1 ) ) + END IF +* +* Decode UPLO +* + IF( UPPER ) THEN + IUPLO = 1 + ELSE + IUPLO = 0 + END IF +* + IF( NB.GE.NRHS ) THEN + CALL ZPTTS2( IUPLO, N, NRHS, D, E, B, LDB ) + ELSE + DO 10 J = 1, NRHS, NB + JB = MIN( NRHS-J+1, NB ) + CALL ZPTTS2( IUPLO, N, JB, D, E, B( 1, J ), LDB ) + 10 CONTINUE + END IF +* + RETURN +* +* End of ZPTTRS +* + END diff --git a/libcruft/lapack/zptts2.f b/libcruft/lapack/zptts2.f new file mode 100644 --- /dev/null +++ b/libcruft/lapack/zptts2.f @@ -0,0 +1,177 @@ + SUBROUTINE ZPTTS2( IUPLO, N, NRHS, D, E, B, LDB ) +* +* -- LAPACK routine (version 3.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* June 30, 1999 +* +* .. Scalar Arguments .. + INTEGER IUPLO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) + COMPLEX*16 B( LDB, * ), E( * ) +* .. +* +* Purpose +* ======= +* +* ZPTTS2 solves a tridiagonal system of the form +* A * X = B +* using the factorization A = U'*D*U or A = L*D*L' computed by ZPTTRF. +* D is a diagonal matrix specified in the vector D, U (or L) is a unit +* bidiagonal matrix whose superdiagonal (subdiagonal) is specified in +* the vector E, and X and B are N by NRHS matrices. +* +* Arguments +* ========= +* +* IUPLO (input) INTEGER +* Specifies the form of the factorization and whether the +* vector E is the superdiagonal of the upper bidiagonal factor +* U or the subdiagonal of the lower bidiagonal factor L. +* = 1: A = U'*D*U, E is the superdiagonal of U +* = 0: A = L*D*L', E is the subdiagonal of L +* +* N (input) INTEGER +* The order of the tridiagonal matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the diagonal matrix D from the +* factorization A = U'*D*U or A = L*D*L'. +* +* E (input) COMPLEX*16 array, dimension (N-1) +* If IUPLO = 1, the (n-1) superdiagonal elements of the unit +* bidiagonal factor U from the factorization A = U'*D*U. +* If IUPLO = 0, the (n-1) subdiagonal elements of the unit +* bidiagonal factor L from the factorization A = L*D*L'. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side vectors B for the system of +* linear equations. +* On exit, the solution vectors, X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Subroutines .. + EXTERNAL ZDSCAL +* .. +* .. Intrinsic Functions .. + INTRINSIC DCONJG +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.1 ) THEN + IF( N.EQ.1 ) + $ CALL ZDSCAL( NRHS, 1.D0 / D( 1 ), B, LDB ) + RETURN + END IF +* + IF( IUPLO.EQ.1 ) THEN +* +* Solve A * X = B using the factorization A = U'*D*U, +* overwriting each right hand side vector with its solution. +* + IF( NRHS.LE.2 ) THEN + J = 1 + 10 CONTINUE +* +* Solve U' * x = b. +* + DO 20 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*DCONJG( E( I-1 ) ) + 20 CONTINUE +* +* Solve D * U * x = b. +* + DO 30 I = 1, N + B( I, J ) = B( I, J ) / D( I ) + 30 CONTINUE + DO 40 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) - B( I+1, J )*E( I ) + 40 CONTINUE + IF( J.LT.NRHS ) THEN + J = J + 1 + GO TO 10 + END IF + ELSE + DO 70 J = 1, NRHS +* +* Solve U' * x = b. +* + DO 50 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*DCONJG( E( I-1 ) ) + 50 CONTINUE +* +* Solve D * U * x = b. +* + B( N, J ) = B( N, J ) / D( N ) + DO 60 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) / D( I ) - B( I+1, J )*E( I ) + 60 CONTINUE + 70 CONTINUE + END IF + ELSE +* +* Solve A * X = B using the factorization A = L*D*L', +* overwriting each right hand side vector with its solution. +* + IF( NRHS.LE.2 ) THEN + J = 1 + 80 CONTINUE +* +* Solve L * x = b. +* + DO 90 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*E( I-1 ) + 90 CONTINUE +* +* Solve D * L' * x = b. +* + DO 100 I = 1, N + B( I, J ) = B( I, J ) / D( I ) + 100 CONTINUE + DO 110 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) - B( I+1, J )*DCONJG( E( I ) ) + 110 CONTINUE + IF( J.LT.NRHS ) THEN + J = J + 1 + GO TO 80 + END IF + ELSE + DO 140 J = 1, NRHS +* +* Solve L * x = b. +* + DO 120 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*E( I-1 ) + 120 CONTINUE +* +* Solve D * L' * x = b. +* + B( N, J ) = B( N, J ) / D( N ) + DO 130 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) / D( I ) - + $ B( I+1, J )*DCONJG( E( I ) ) + 130 CONTINUE + 140 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZPTTS2 +* + END diff --git a/liboctave/CNDArray.cc b/liboctave/CNDArray.cc --- a/liboctave/CNDArray.cc +++ b/liboctave/CNDArray.cc @@ -26,6 +26,7 @@ #endif #include + #include #include "Array-util.h" diff --git a/liboctave/COLAMD.README b/liboctave/COLAMD.README new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD.README @@ -0,0 +1,25 @@ +This directory contains an unmodified copy of COLAMD version 2.3 in +the subdirectory COLAMD. COLAMD was written by Stefan I. Larimore and +Timothy A. Davis (davis@cise.ufl.edu), University of Florida. The +algorithm was developed in collaboration with John Gilbert, Xerox +PARC, and Esmond Ng, Oak Ridge National Laboratory. COLAMD is +distributed under the following terms: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use, copy, modify, and/or distribute + this program, provided that the Copyright, this License, and the + Availability of the original version is retained on all copies and made + accessible to the end-user of any code or package that includes COLAMD + or any modified version of COLAMD. + +John W. Eaton +jwe@bevo.che.wisc.edu +University of Wisconsin-Madison +Department of Chemical & Biological Engineering + +Wed Dec 29 20:20:56 2004 diff --git a/liboctave/COLAMD.files b/liboctave/COLAMD.files new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD.files @@ -0,0 +1,11 @@ + +COLAMD_SRC := colamd.c + +COLAMD_OBJ := $(COLAMD_SRC:.c=.o) + +COLAMD_DEP := $(COLAMD_SRC:.c=.d) + +$(COLAMD_OBJ) $(COLAMD_DEP) := INCFLAGS += -I$(top_srcdir)/liboctave/COLAMD + +COLAMD_EXTRAS := COLAMD.files COLAMD.README + diff --git a/liboctave/COLAMD/ChangeLog b/liboctave/COLAMD/ChangeLog new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/ChangeLog @@ -0,0 +1,69 @@ + Changes from Version 2.2 to 2.3 (Sept. 8, 2003) + + * removed the call to the MATLAB spparms ('spumoni') function. + This can take a lot of time if you are ordering many small + matrices. Only affects the MATLAB interface (colamdmex.c, + symamdmex.c, colamdtestmex.c, and symamdtestmex.c). The + usage of the optional 2nd argument to the colamd and symamd + mexFunctions was changed accordingly. + + Changes from Version 2.1 to 2.2 (Sept. 23, 2002) + + * extensive testing routines added (colamd_test.m, colamdtestmex.c, + and symamdtestmex.c), and the Makefile modified accordingly. + + * a few typos in the comments corrected + + * use of the MATLAB "flops" command removed from colamd_demo, and an + m-file routine luflops.m added. + + * an explicit typecast from unsigned to int added, for COLAMD_C and + COLAMD_R in colamd.h. + + * #include added to colamd_example.c + + + Changes from Version 2.0 to 2.1 (May 4, 2001) + + * TRUE and FALSE are predefined on some systems, so they are defined + here only if not already defined. + + * web site changed + + * UNIX Makefile modified, to handle the case if "." is not in your path. + + + Changes from Version 1.0 to 2.0 (January 31, 2000) + + No bugs were found in version 1.1. These changes merely add new + functionality. + + * added the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. + + * moved the output statistics, from A, to a separate output argument. + The arguments changed for the C-callable routines. + + * added colamd_report and symamd_report. + + * added a C-callable symamd routine. Formerly, symamd was only + available as a mexFunction from MATLAB. + + * added error-checking to symamd. Formerly, it assumed its input + was error-free. + + * added the optional stats and knobs arguments to the symamd mexFunction + + * deleted colamd_help. A help message is still available from + "help colamd" and "help symamd" in MATLAB. + + * deleted colamdtree.m and symamdtree.m. Now, colamd.m and symamd.m + also do the elimination tree post-ordering. The Version 1.1 + colamd and symamd mexFunctions, which do not do the post- + ordering, are now visible as colamdmex and symamdmex from + MATLAB. Essentialy, the post-ordering is now the default + behavior of colamd.m and symamd.m, to match the behavior of + colmmd and symmmd. The post-ordering is only available in the + MATLAB interface, not the C-callable interface. + + * made a slight change to the dense row/column detection in symamd, + to match the stated specifications. diff --git a/liboctave/COLAMD/Makefile b/liboctave/COLAMD/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/Makefile @@ -0,0 +1,19 @@ +colamd_example: colamd_example.c colamd.c colamd.h + cc -O -o colamd_example colamd_example.c colamd.c + - ./colamd_example + +clean: + - rm *.o colamd_example + - rm colamdmex.mex* symamdmex.mex* + - rm colamdtestmex.mex* symamdtestmex.mex* + +# Compiles the MATLAB-callable routines +matlab: colamdmex.c colamd.c colamd.h + mex -O colamdmex.c colamd.c + mex -O symamdmex.c colamd.c + +# Compiles the extensive test code +test: matlab colamdmex.c colamd.c colamd.h + mex -O colamdtestmex.c colamd.c + mex -O symamdtestmex.c colamd.c + diff --git a/liboctave/COLAMD/README b/liboctave/COLAMD/README new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/README @@ -0,0 +1,104 @@ +The COLAMD ordering method - Version 2.3 +------------------------------------------------------------------------------- + +The COLAMD column approximate minimum degree ordering algorithm computes +a permutation vector P such that the LU factorization of A (:,P) +tends to be sparser than that of A. The Cholesky factorization of +(A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A. +SYMAMD is a symmetric minimum degree ordering method based on COLAMD, +available as a MATLAB-callable function. It constructs a matrix M such +that M'*M has the same pattern as A, and then uses COLAMD to compute a column +ordering of M. Colamd and symamd tend to be faster and generate better +orderings than their MATLAB counterparts, colmmd and symmmd. + +To compile and test the colamd m-files and mexFunctions, just unpack the +colamd2.3/ directory from the colamd2.3.tar.gz file, and run MATLAB from +within that directory. Next, type colamd_test to compile and test colamd +and symamd. This will work on any computer with MATLAB (Unix, PC, or Mac). +Alternatively, type "make" (in Unix) to compile and run a simple example C +code, without using MATLAB. + +Colamd 2.0 is a built-in routine in MATLAB V6.0, available from The +Mathworks, Inc. Under most cases, the compiled codes from Versions 2.0 +through 2.2 do not differ. Colamd Versions 2.2 and 2.3 differ only in their +mexFunction interaces to MATLAB. + +To use colamd and symamd within an application written in C, all you need are +colamd.c and colamd.h, which are the C-callable colamd/symamd codes. +See colamd.c for more information on how to call colamd from a C program. + + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c + file) for the License. + + +Related papers: + + "A column approximate minimum degree ordering algorithm", Timothy A. + Davis, John R. Gilbert, Stefan I. Larimore, and Esmond G. Ng. + ACM Trans. on Mathematical Software. + + "Algorithm 8xx: COLAMD, a column approximate minimum degree ordering + algorithm", Timothy A. Davis, John R. Gilbert, Stefan I. Larimore, and + Esmond G. Ng. ACM Trans. on Mathematical Software. + + "An approximate minimum degree column ordering algorithm", + S. I. Larimore, MS Thesis, Dept. of Computer and Information + Science and Engineering, University of Florida, Gainesville, FL, + 1998. CISE Tech Report TR-98-016. Available at + ftp://ftp.cise.ufl.edu/cis/tech-reports/tr98/tr98-016.ps + via anonymous ftp. + + Approximate Deficiency for Ordering the Columns of a Matrix, + J. L. Kern, Senior Thesis, Dept. of Computer and Information + Science and Engineering, University of Florida, Gainesville, FL, + 1999. Available at http://www.cise.ufl.edu/~davis/Kern/kern.ps + + +Authors: Stefan I. Larimore and Timothy A. Davis, University of Florida, +in collaboration with John Gilbert, Xerox PARC (now at UC Santa Barbara), +and Esmong Ng, Lawrence Berkeley National Laboratory (much of this work +he did while at Oak Ridge National Laboratory). + +COLAMD files (Version 2.3, September 8, 2003): + + colamd2.3.tar.gz: + All files, as a gzipped, Unix tar file. + The *.m, and *mex.c files are for use in MATLAB. + + colamd.c: the primary colamd computational kernel. + + colamd.h: include file for colamd/symamd library. + + colamd.m: the MATLAB interface to colamd. + + colamd_demo.m: MATLAB demo file for colamd and symamd + (also compiles the colamdmex and symamdmex mexFunctions). + + colamdmex.c: colamd mexFunction for use in MATLAB. + + colamd_example.c: example C main program that calls colamd and symamd. + + colamd_example.out: output of colamd_example.c. + + Makefile: Makefile for colamd_example.c + + symamd.m: the MATLAB interface to symamd. + + symamdmex.c: symamd mexFunction for use in MATLAB. + + README: this file + + ChangeLog: a log of changes since Version 1.0. + + colamd_test.m: test code + + colamdtestmex.c: test code + + luflops.m: test code + + symamdtestmex.c: test code + diff --git a/liboctave/COLAMD/colamd.c b/liboctave/COLAMD/colamd.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd.c @@ -0,0 +1,3412 @@ +/* ========================================================================== */ +/* === colamd/symamd - a sparse matrix column ordering algorithm ============ */ +/* ========================================================================== */ + +/* + colamd: an approximate minimum degree column ordering algorithm, + for LU factorization of symmetric or unsymmetric matrices, + QR factorization, least squares, interior point methods for + linear programming problems, and other related problems. + + symamd: an approximate minimum degree ordering algorithm for Cholesky + factorization of symmetric matrices. + + Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization of + (AQ)'(AQ) has less fill-in and requires fewer floating point operations + than A'A. This also provides a good ordering for sparse partial + pivoting methods, P(AQ) = LU, where Q is computed prior to numerical + factorization, and P is computed during numerical factorization via + conventional partial pivoting with row interchanges. Colamd is the + column ordering method used in SuperLU, part of the ScaLAPACK library. + It is also available as built-in function in MATLAB Version 6, + available from MathWorks, Inc. (http://www.mathworks.com). This + routine can be used in place of colmmd in MATLAB. + + Symamd computes a permutation P of a symmetric matrix A such that the + Cholesky factorization of PAP' has less fill-in and requires fewer + floating point operations than A. Symamd constructs a matrix M such + that M'M has the same nonzero pattern of A, and then orders the columns + of M using colmmd. The column ordering of M is then returned as the + row and column ordering P of A. + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Copyright and License: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use, copy, modify, and/or distribute + this program, provided that the Copyright, this License, and the + Availability of the original version is retained on all copies and made + accessible to the end-user of any code or package that includes COLAMD + or any modified version of COLAMD. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c + file. It requires the colamd.h file. It is required by the colamdmex.c + and symamdmex.c files, for the MATLAB interface to colamd and symamd. + + See the ChangeLog file for changes since Version 1.0. + +*/ + +/* ========================================================================== */ +/* === Description of user-callable routines ================================ */ +/* ========================================================================== */ + +/* + ---------------------------------------------------------------------------- + colamd_recommended: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int colamd_recommended (int nnz, int n_row, int n_col) ; + + or as a C macro + + #include "colamd.h" + Alen = COLAMD_RECOMMENDED (int nnz, int n_row, int n_col) ; + + Purpose: + + Returns recommended value of Alen for use by colamd. Returns -1 + if any input argument is negative. The use of this routine + or macro is optional. Note that the macro uses its arguments + more than once, so be careful for side effects, if you pass + expressions as arguments to COLAMD_RECOMMENDED. Not needed for + symamd, which dynamically allocates its own memory. + + Arguments (all input arguments): + + int nnz ; Number of nonzeros in the matrix A. This must + be the same value as p [n_col] in the call to + colamd - otherwise you will get a wrong value + of the recommended memory to use. + + int n_row ; Number of rows in the matrix A. + + int n_col ; Number of columns in the matrix A. + + ---------------------------------------------------------------------------- + colamd_set_defaults: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; + + Purpose: + + Sets the default parameters. The use of this routine is optional. + + Arguments: + + double knobs [COLAMD_KNOBS] ; Output only. + + Colamd: rows with more than (knobs [COLAMD_DENSE_ROW] * n_col) + entries are removed prior to ordering. Columns with more than + (knobs [COLAMD_DENSE_COL] * n_row) entries are removed prior to + ordering, and placed last in the output column ordering. + + Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0]. + Rows and columns with more than (knobs [COLAMD_DENSE_ROW] * n) + entries are removed prior to ordering, and placed last in the + output ordering. + + COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, + respectively, in colamd.h. Default values of these two knobs + are both 0.5. Currently, only knobs [0] and knobs [1] are + used, but future versions may use more knobs. If so, they will + be properly set to their defaults by the future version of + colamd_set_defaults, so that the code that calls colamd will + not need to change, assuming that you either use + colamd_set_defaults, or pass a (double *) NULL pointer as the + knobs array to colamd or symamd. + + ---------------------------------------------------------------------------- + colamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int colamd (int n_row, int n_col, int Alen, int *A, int *p, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ; + + Purpose: + + Computes a column ordering (Q) of A such that P(AQ)=LU or + (AQ)'AQ=LL' have less fill-in and require fewer floating point + operations than factorizing the unpermuted matrix A or A'A, + respectively. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n_row ; Input argument. + + Number of rows in the matrix A. + Restriction: n_row >= 0. + Colamd returns FALSE if n_row is negative. + + int n_col ; Input argument. + + Number of columns in the matrix A. + Restriction: n_col >= 0. + Colamd returns FALSE if n_col is negative. + + int Alen ; Input argument. + + Restriction (see note): + Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col + Colamd returns FALSE if these conditions are not met. + + Note: this restriction makes an modest assumption regarding + the size of the two typedef's structures in colamd.h. + We do, however, guarantee that + + Alen >= colamd_recommended (nnz, n_row, n_col) + + or equivalently as a C preprocessor macro: + + Alen >= COLAMD_RECOMMENDED (nnz, n_row, n_col) + + will be sufficient. + + int A [Alen] ; Input argument, undefined on output. + + A is an integer array of size Alen. Alen must be at least as + large as the bare minimum value given above, but this is very + low, and can result in excessive run time. For best + performance, we recommend that Alen be greater than or equal to + colamd_recommended (nnz, n_row, n_col), which adds + nnz/5 to the bare minimum value given above. + + On input, the row indices of the entries in column c of the + matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices + in a given column c need not be in ascending order, and + duplicate row indices may be be present. However, colamd will + work a little faster if both of these conditions are met + (Colamd puts the matrix into this format, if it finds that the + the conditions are not met). + + The matrix is 0-based. That is, rows are in the range 0 to + n_row-1, and columns are in the range 0 to n_col-1. Colamd + returns FALSE if any row index is out of range. + + The contents of A are modified during ordering, and are + undefined on output. + + int p [n_col+1] ; Both input and output argument. + + p is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n_col-1. The value p [n_col] is + thus the total number of entries in the pattern of the matrix A. + Colamd returns FALSE if these conditions are not met. + + On output, if colamd returns TRUE, the array p holds the column + permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is + the first column index in the new ordering, and p [n_col-1] is + the last. That is, p [k] = j means that column j of A is the + kth pivot column, in AQ, where k is in the range 0 to n_col-1 + (p [0] = j means that column j of A is the first column in AQ). + + If colamd returns FALSE, then no permutation is returned, and + p is undefined on output. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Colamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty rows ignored. + + stats [1]: number of dense or empty columns ignored (and + ordered last in the output permutation p) + Note that a row can become "empty" if it + contains only "dense" and/or "empty" columns, + and similarly a column can become "empty" if it + only contains "dense" and/or "empty" rows. + + stats [2]: number of garbage collections performed. + This can be excessively high if Alen is close + to the minimum required value. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Colamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of colamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 n_row is negative + + stats [4]: n_row + + -4 n_col is negative + + stats [4]: n_col + + -5 number of nonzeros in matrix is negative + + stats [4]: number of nonzeros, p [n_col] + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 A is too small + + stats [4]: required size + stats [5]: actual size (Alen) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 (unused; see symamd.c) + + -999 (unused; see symamd.c) + + Future versions may return more statistics in the stats array. + + Example: + + See http://www.cise.ufl.edu/research/sparse/colamd/example.c + for a complete example. + + To order the columns of a 5-by-4 matrix with 11 nonzero entries in + the following nonzero pattern + + x 0 x 0 + x 0 x x + 0 x x 0 + 0 0 x x + x x 0 0 + + with default knobs and no output statistics, do the following: + + #include "colamd.h" + #define ALEN COLAMD_RECOMMENDED (11, 5, 4) + int A [ALEN] = {1, 2, 5, 3, 5, 1, 2, 3, 4, 2, 4} ; + int p [ ] = {0, 3, 5, 9, 11} ; + int stats [COLAMD_STATS] ; + colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; + + The permutation is returned in the array p, and A is destroyed. + + ---------------------------------------------------------------------------- + symamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int symamd (int n, int *A, int *p, int *perm, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; + + Purpose: + + The symamd routine computes an ordering P of a symmetric sparse + matrix A such that the Cholesky factorization PAP' = LL' remains + sparse. It is based on a column ordering of a matrix M constructed + so that the nonzero pattern of M'M is the same as A. The matrix A + is assumed to be symmetric; only the strictly lower triangular part + is accessed. You must pass your selected memory allocator (usually + calloc/free or mxCalloc/mxFree) to symamd, for it to allocate + memory for the temporary matrix M. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n ; Input argument. + + Number of rows and columns in the symmetrix matrix A. + Restriction: n >= 0. + Symamd returns FALSE if n is negative. + + int A [nnz] ; Input argument. + + A is an integer array of size nnz, where nnz = p [n]. + + The row indices of the entries in column c of the matrix are + held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a + given column c need not be in ascending order, and duplicate + row indices may be present. However, symamd will run faster + if the columns are in sorted order with no duplicate entries. + + The matrix is 0-based. That is, rows are in the range 0 to + n-1, and columns are in the range 0 to n-1. Symamd + returns FALSE if any row index is out of range. + + The contents of A are not modified. + + int p [n+1] ; Input argument. + + p is an integer array of size n+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n-1. The value p [n] is + thus the total number of entries in the pattern of the matrix A. + Symamd returns FALSE if these conditions are not met. + + The contents of p are not modified. + + int perm [n+1] ; Output argument. + + On output, if symamd returns TRUE, the array perm holds the + permutation P, where perm [0] is the first index in the new + ordering, and perm [n-1] is the last. That is, perm [k] = j + means that row and column j of A is the kth column in PAP', + where k is in the range 0 to n-1 (perm [0] = j means + that row and column j of A are the first row and column in + PAP'). The array is used as a workspace during the ordering, + which is why it must be of length n+1, not just n. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Symamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty row and columns ignored + (and ordered last in the output permutation + perm). Note that a row/column can become + "empty" if it contains only "dense" and/or + "empty" columns/rows. + + stats [1]: (same as stats [0]) + + stats [2]: number of garbage collections performed. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Symamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of symamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 (unused, see colamd.c) + + -4 n is negative + + stats [4]: n + + -5 number of nonzeros in matrix is negative + + stats [4]: # of nonzeros (p [n]). + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 (unused) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 out of memory (unable to allocate temporary + workspace for M or count arrays using the + "allocate" routine passed into symamd). + + -999 internal error. colamd failed to order the + matrix M, when it should have succeeded. This + indicates a bug. If this (and *only* this) + error code occurs, please contact the authors. + Don't contact the authors if you get any other + error code. + + Future versions may return more statistics in the stats array. + + void * (*allocate) (size_t, size_t) + + A pointer to a function providing memory allocation. The + allocated memory must be returned initialized to zero. For a + C application, this argument should normally be a pointer to + calloc. For a MATLAB mexFunction, the routine mxCalloc is + passed instead. + + void (*release) (size_t, size_t) + + A pointer to a function that frees memory allocated by the + memory allocation routine above. For a C application, this + argument should normally be a pointer to free. For a MATLAB + mexFunction, the routine mxFree is passed instead. + + + ---------------------------------------------------------------------------- + colamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_report (int stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from colamd. + + + ---------------------------------------------------------------------------- + symamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + symamd_report (int stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from symamd. + + +*/ + +/* ========================================================================== */ +/* === Scaffolding code definitions ======================================== */ +/* ========================================================================== */ + +/* Ensure that debugging is turned off: */ +#ifndef NDEBUG +#define NDEBUG +#endif /* NDEBUG */ + +/* + Our "scaffolding code" philosophy: In our opinion, well-written library + code should keep its "debugging" code, and just normally have it turned off + by the compiler so as not to interfere with performance. This serves + several purposes: + + (1) assertions act as comments to the reader, telling you what the code + expects at that point. All assertions will always be true (unless + there really is a bug, of course). + + (2) leaving in the scaffolding code assists anyone who would like to modify + the code, or understand the algorithm (by reading the debugging output, + one can get a glimpse into what the code is doing). + + (3) (gasp!) for actually finding bugs. This code has been heavily tested + and "should" be fully functional and bug-free ... but you never know... + + To enable debugging, comment out the "#define NDEBUG" above. For a MATLAB + mexFunction, you will also need to modify mexopts.sh to remove the -DNDEBUG + definition. The code will become outrageously slow when debugging is + enabled. To control the level of debugging output, set an environment + variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, + you should see the following message on the standard output: + + colamd: debug version, D = 1 (THIS WILL BE SLOW!) + + or a similar message for symamd. If you don't, then debugging has not + been enabled. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" +#include + +#ifdef MATLAB_MEX_FILE +#include "mex.h" +#include "matrix.h" +#else +#include +#include +#endif /* MATLAB_MEX_FILE */ + +/* ========================================================================== */ +/* === Definitions ========================================================== */ +/* ========================================================================== */ + +/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */ +#define PUBLIC +#define PRIVATE static + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define ONES_COMPLEMENT(r) (-(r)-1) + +/* -------------------------------------------------------------------------- */ +/* Change for version 2.1: define TRUE and FALSE only if not yet defined */ +/* -------------------------------------------------------------------------- */ + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ + +#define EMPTY (-1) + +/* Row and column status */ +#define ALIVE (0) +#define DEAD (-1) + +/* Column status */ +#define DEAD_PRINCIPAL (-1) +#define DEAD_NON_PRINCIPAL (-2) + +/* Macros for row and column status update and checking. */ +#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) +#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) +#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) +#define COL_IS_DEAD(c) (Col [c].start < ALIVE) +#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) +#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) +#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } +#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } +#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } + +/* ========================================================================== */ +/* === Colamd reporting mechanism =========================================== */ +/* ========================================================================== */ + +#ifdef MATLAB_MEX_FILE + +/* use mexPrintf in a MATLAB mexFunction, for debugging and statistics output */ +#define PRINTF mexPrintf + +/* In MATLAB, matrices are 1-based to the user, but 0-based internally */ +#define INDEX(i) ((i)+1) + +#else + +/* Use printf in standard C environment, for debugging and statistics output. */ +/* Output is generated only if debugging is enabled at compile time, or if */ +/* the caller explicitly calls colamd_report or symamd_report. */ +#define PRINTF printf + +/* In C, matrices are 0-based and indices are reported as such in *_report */ +#define INDEX(i) (i) + +#endif /* MATLAB_MEX_FILE */ + +/* ========================================================================== */ +/* === Prototypes of PRIVATE routines ======================================= */ +/* ========================================================================== */ + +PRIVATE int init_rows_cols +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int p [], + int stats [COLAMD_STATS] +) ; + +PRIVATE void init_scoring +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int head [], + double knobs [COLAMD_KNOBS], + int *p_n_row2, + int *p_n_col2, + int *p_max_deg +) ; + +PRIVATE int find_ordering +( + int n_row, + int n_col, + int Alen, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int head [], + int n_col2, + int max_deg, + int pfree +) ; + +PRIVATE void order_children +( + int n_col, + Colamd_Col Col [], + int p [] +) ; + +PRIVATE void detect_super_cols +( + +#ifndef NDEBUG + int n_col, + Colamd_Row Row [], +#endif /* NDEBUG */ + + Colamd_Col Col [], + int A [], + int head [], + int row_start, + int row_length +) ; + +PRIVATE int garbage_collection +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int *pfree +) ; + +PRIVATE int clear_mark +( + int n_row, + Colamd_Row Row [] +) ; + +PRIVATE void print_report +( + char *method, + int stats [COLAMD_STATS] +) ; + +/* ========================================================================== */ +/* === Debugging prototypes and definitions ================================= */ +/* ========================================================================== */ + +#ifndef NDEBUG + +/* colamd_debug is the *ONLY* global variable, and is only */ +/* present when debugging */ + +PRIVATE int colamd_debug ; /* debug print level */ + +#define DEBUG0(params) { (void) PRINTF params ; } +#define DEBUG1(params) { if (colamd_debug >= 1) (void) PRINTF params ; } +#define DEBUG2(params) { if (colamd_debug >= 2) (void) PRINTF params ; } +#define DEBUG3(params) { if (colamd_debug >= 3) (void) PRINTF params ; } +#define DEBUG4(params) { if (colamd_debug >= 4) (void) PRINTF params ; } + +#ifdef MATLAB_MEX_FILE +#define ASSERT(expression) (mxAssert ((expression), "")) +#else +#define ASSERT(expression) (assert (expression)) +#endif /* MATLAB_MEX_FILE */ + +PRIVATE void colamd_get_debug /* gets the debug print level from getenv */ +( + char *method +) ; + +PRIVATE void debug_deg_lists +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int head [], + int min_score, + int should, + int max_deg +) ; + +PRIVATE void debug_mark +( + int n_row, + Colamd_Row Row [], + int tag_mark, + int max_mark +) ; + +PRIVATE void debug_matrix +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [] +) ; + +PRIVATE void debug_structures +( + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int n_col2 +) ; + +#else /* NDEBUG */ + +/* === No debugging ========================================================= */ + +#define DEBUG0(params) ; +#define DEBUG1(params) ; +#define DEBUG2(params) ; +#define DEBUG3(params) ; +#define DEBUG4(params) ; + +#define ASSERT(expression) ((void) 0) + +#endif /* NDEBUG */ + +/* ========================================================================== */ + + + +/* ========================================================================== */ +/* === USER-CALLABLE ROUTINES: ============================================== */ +/* ========================================================================== */ + + +/* ========================================================================== */ +/* === colamd_recommended =================================================== */ +/* ========================================================================== */ + +/* + The colamd_recommended routine returns the suggested size for Alen. This + value has been determined to provide good balance between the number of + garbage collections and the memory requirements for colamd. If any + argument is negative, a -1 is returned as an error condition. This + function is also available as a macro defined in colamd.h, so that you + can use it for a statically-allocated array size. +*/ + +PUBLIC int colamd_recommended /* returns recommended value of Alen. */ +( + /* === Parameters ======================================================= */ + + int nnz, /* number of nonzeros in A */ + int n_row, /* number of rows in A */ + int n_col /* number of columns in A */ +) +{ + return (COLAMD_RECOMMENDED (nnz, n_row, n_col)) ; +} + + +/* ========================================================================== */ +/* === colamd_set_defaults ================================================== */ +/* ========================================================================== */ + +/* + The colamd_set_defaults routine sets the default values of the user- + controllable parameters for colamd: + + knobs [0] rows with knobs[0]*n_col entries or more are removed + prior to ordering in colamd. Rows and columns with + knobs[0]*n_col entries or more are removed prior to + ordering in symamd and placed last in the output + ordering. + + knobs [1] columns with knobs[1]*n_row entries or more are removed + prior to ordering in colamd, and placed last in the + column permutation. Symamd ignores this knob. + + knobs [2..19] unused, but future versions might use this +*/ + +PUBLIC void colamd_set_defaults +( + /* === Parameters ======================================================= */ + + double knobs [COLAMD_KNOBS] /* knob array */ +) +{ + /* === Local variables ================================================== */ + + int i ; + + if (!knobs) + { + return ; /* no knobs to initialize */ + } + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + knobs [i] = 0 ; + } + knobs [COLAMD_DENSE_ROW] = 0.5 ; /* ignore rows over 50% dense */ + knobs [COLAMD_DENSE_COL] = 0.5 ; /* ignore columns over 50% dense */ +} + + +/* ========================================================================== */ +/* === symamd =============================================================== */ +/* ========================================================================== */ + +PUBLIC int symamd /* return TRUE if OK, FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + int n, /* number of rows and columns of A */ + int A [], /* row indices of A */ + int p [], /* column pointers of A */ + int perm [], /* output permutation, size n+1 */ + double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ + int stats [COLAMD_STATS], /* output statistics and error codes */ + void * (*allocate) (size_t, size_t), + /* pointer to calloc (ANSI C) or */ + /* mxCalloc (for MATLAB mexFunction) */ + void (*release) (void *) + /* pointer to free (ANSI C) or */ + /* mxFree (for MATLAB mexFunction) */ +) +{ + /* === Local variables ================================================== */ + + int *count ; /* length of each column of M, and col pointer*/ + int *mark ; /* mark array for finding duplicate entries */ + int *M ; /* row indices of matrix M */ + int Mlen ; /* length of M */ + int n_row ; /* number of rows in M */ + int nnz ; /* number of entries in A */ + int i ; /* row index of A */ + int j ; /* column index of A */ + int k ; /* row index of M */ + int mnz ; /* number of nonzeros in M */ + int pp ; /* index into a column of A */ + int last_row ; /* last row seen in the current column */ + int length ; /* number of nonzeros in a column */ + + double cknobs [COLAMD_KNOBS] ; /* knobs for colamd */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs for colamd */ + int cstats [COLAMD_STATS] ; /* colamd stats */ + +#ifndef NDEBUG + colamd_get_debug ("symamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("symamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("symamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("symamd: p not present\n")) ; + return (FALSE) ; + } + + if (n < 0) /* n must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n ; + DEBUG0 (("symamd: n negative %d\n", n)) ; + return (FALSE) ; + } + + nnz = p [n] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + colamd_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + /* === Allocate count and mark ========================================== */ + + count = (int *) ((*allocate) (n+1, sizeof (int))) ; + if (!count) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + mark = (int *) ((*allocate) (n+1, sizeof (int))) ; + if (!mark) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + /* === Compute column counts of M, check if A is valid ================== */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + + for (j = 0 ; j < n ; j++) + { + last_row = -1 ; + + length = p [j+1] - p [j] ; + if (length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = length ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ; + return (FALSE) ; + } + + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + if (i < 0 || i >= n) + { + /* row index i, in column j, is out of bounds */ + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + stats [COLAMD_INFO3] = n ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ; + return (FALSE) ; + } + + if (i <= last_row || mark [i] == j) + { + /* row index is unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ; + } + + if (i > j && mark [i] != j) + { + /* row k of M will contain column indices i and j */ + count [i]++ ; + count [j]++ ; + } + + /* mark the row as having been seen in this column */ + mark [i] = j ; + + last_row = i ; + } + } + + if (stats [COLAMD_STATUS] == COLAMD_OK) + { + /* if there are no duplicate entries, then mark is no longer needed */ + (*release) ((void *) mark) ; + } + + /* === Compute column pointers of M ===================================== */ + + /* use output permutation, perm, for column pointers of M */ + perm [0] = 0 ; + for (j = 1 ; j <= n ; j++) + { + perm [j] = perm [j-1] + count [j-1] ; + } + for (j = 0 ; j < n ; j++) + { + count [j] = perm [j] ; + } + + /* === Construct M ====================================================== */ + + mnz = perm [n] ; + n_row = mnz / 2 ; + Mlen = colamd_recommended (mnz, n_row, n) ; + M = (int *) ((*allocate) (Mlen, sizeof (int))) ; + DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %d\n", + n_row, n, mnz, Mlen)) ; + + if (!M) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: allocate M (size %d) failed\n", Mlen)) ; + return (FALSE) ; + } + + k = 0 ; + + if (stats [COLAMD_STATUS] == COLAMD_OK) + { + /* Matrix is OK */ + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + } + } + } + } + else + { + /* Matrix is jumbled. Do not add duplicates to M. Unsorted cols OK. */ + DEBUG0 (("symamd: Duplicates in A.\n")) ; + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j && mark [i] != j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + mark [i] = j ; + } + } + } + (*release) ((void *) mark) ; + } + + /* count and mark no longer needed */ + (*release) ((void *) count) ; + ASSERT (k == n_row) ; + + /* === Adjust the knobs for M =========================================== */ + + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + cknobs [i] = knobs [i] ; + } + + /* there are no dense rows in M */ + cknobs [COLAMD_DENSE_ROW] = 1.0 ; + + if (n_row != 0 && n < n_row) + { + /* On input, the knob is a fraction of 1..n, the number of rows of A. */ + /* Convert it to a fraction of 1..n_row, of the number of rows of M. */ + cknobs [COLAMD_DENSE_COL] = (knobs [COLAMD_DENSE_ROW] * n) / n_row ; + } + else + { + /* no dense columns in M */ + cknobs [COLAMD_DENSE_COL] = 1.0 ; + } + + DEBUG0 (("symamd: dense col knob for M: %g\n", cknobs [COLAMD_DENSE_COL])) ; + + /* === Order the columns of M =========================================== */ + + if (!colamd (n_row, n, Mlen, M, perm, cknobs, cstats)) + { + /* This "cannot" happen, unless there is a bug in the code. */ + stats [COLAMD_STATUS] = COLAMD_ERROR_internal_error ; + (*release) ((void *) M) ; + DEBUG0 (("symamd: internal error!\n")) ; + return (FALSE) ; + } + + /* Note that the output permutation is now in perm */ + + /* === get the statistics for symamd from colamd ======================== */ + + /* note that a dense column in colamd means a dense row and col in symamd */ + stats [COLAMD_DENSE_ROW] = cstats [COLAMD_DENSE_COL] ; + stats [COLAMD_DENSE_COL] = cstats [COLAMD_DENSE_COL] ; + stats [COLAMD_DEFRAG_COUNT] = cstats [COLAMD_DEFRAG_COUNT] ; + + /* === Free M =========================================================== */ + + (*release) ((void *) M) ; + DEBUG0 (("symamd: done.\n")) ; + return (TRUE) ; + +} + +/* ========================================================================== */ +/* === colamd =============================================================== */ +/* ========================================================================== */ + +/* + The colamd routine computes a column ordering Q of a sparse matrix + A such that the LU factorization P(AQ) = LU remains sparse, where P is + selected via partial pivoting. The routine can also be viewed as + providing a permutation Q such that the Cholesky factorization + (AQ)'(AQ) = LL' remains sparse. +*/ + +PUBLIC int colamd /* returns TRUE if successful, FALSE otherwise*/ +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows in A */ + int n_col, /* number of columns in A */ + int Alen, /* length of A */ + int A [], /* row indices of A */ + int p [], /* pointers to columns in A */ + double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ + int stats [COLAMD_STATS] /* output statistics and error codes */ +) +{ + /* === Local variables ================================================== */ + + int i ; /* loop index */ + int nnz ; /* nonzeros in A */ + int Row_size ; /* size of Row [], in integers */ + int Col_size ; /* size of Col [], in integers */ + int need ; /* minimum required length of A */ + Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ + Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ + int n_col2 ; /* number of non-dense, non-empty columns */ + int n_row2 ; /* number of non-dense, non-empty rows */ + int ngarbage ; /* number of garbage collections performed */ + int max_deg ; /* maximum row degree */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ + +#ifndef NDEBUG + colamd_get_debug ("colamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("colamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) /* A is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("colamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("colamd: p not present\n")) ; + return (FALSE) ; + } + + if (n_row < 0) /* n_row must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ; + stats [COLAMD_INFO1] = n_row ; + DEBUG0 (("colamd: nrow negative %d\n", n_row)) ; + return (FALSE) ; + } + + if (n_col < 0) /* n_col must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n_col ; + DEBUG0 (("colamd: ncol negative %d\n", n_col)) ; + return (FALSE) ; + } + + nnz = p [n_col] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + colamd_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + /* === Allocate the Row and Col arrays from array A ===================== */ + + Col_size = COLAMD_C (n_col) ; + Row_size = COLAMD_R (n_row) ; + need = 2*nnz + n_col + Col_size + Row_size ; + + if (need > Alen) + { + /* not enough space in array A to perform the ordering */ + stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ; + stats [COLAMD_INFO1] = need ; + stats [COLAMD_INFO2] = Alen ; + DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen)); + return (FALSE) ; + } + + Alen -= Col_size + Row_size ; + Col = (Colamd_Col *) &A [Alen] ; + Row = (Colamd_Row *) &A [Alen + Col_size] ; + + /* === Construct the row and column data structures ===================== */ + + if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats)) + { + /* input matrix is invalid */ + DEBUG0 (("colamd: Matrix invalid\n")) ; + return (FALSE) ; + } + + /* === Initialize scores, kill dense rows/columns ======================= */ + + init_scoring (n_row, n_col, Row, Col, A, p, knobs, + &n_row2, &n_col2, &max_deg) ; + + /* === Order the supercolumns =========================================== */ + + ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, + n_col2, max_deg, 2*nnz) ; + + /* === Order the non-principal columns ================================== */ + + order_children (n_col, Col, p) ; + + /* === Return statistics in stats ======================================= */ + + stats [COLAMD_DENSE_ROW] = n_row - n_row2 ; + stats [COLAMD_DENSE_COL] = n_col - n_col2 ; + stats [COLAMD_DEFRAG_COUNT] = ngarbage ; + DEBUG0 (("colamd: done.\n")) ; + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === colamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void colamd_report +( + int stats [COLAMD_STATS] +) +{ + print_report ("colamd", stats) ; +} + + +/* ========================================================================== */ +/* === symamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void symamd_report +( + int stats [COLAMD_STATS] +) +{ + print_report ("symamd", stats) ; +} + + + +/* ========================================================================== */ +/* === NON-USER-CALLABLE ROUTINES: ========================================== */ +/* ========================================================================== */ + +/* There are no user-callable routines beyond this point in the file */ + + +/* ========================================================================== */ +/* === init_rows_cols ======================================================= */ +/* ========================================================================== */ + +/* + Takes the column form of the matrix in A and creates the row form of the + matrix. Also, row and column attributes are stored in the Col and Row + structs. If the columns are un-sorted or contain duplicate row indices, + this routine will also sort and remove duplicate row indices from the + column form of the matrix. Returns FALSE if the matrix is invalid, + TRUE otherwise. Not user-callable. +*/ + +PRIVATE int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows of A */ + int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + int A [], /* row indices of A, of size Alen */ + int p [], /* pointers to columns in A, of size n_col+1 */ + int stats [COLAMD_STATS] /* colamd statistics */ +) +{ + /* === Local variables ================================================== */ + + int col ; /* a column index */ + int row ; /* a row index */ + int *cp ; /* a column pointer */ + int *cp_end ; /* a pointer to the end of a column */ + int *rp ; /* a row pointer */ + int *rp_end ; /* a pointer to the end of a row */ + int last_row ; /* previous row */ + + /* === Initialize columns, and check column pointers ==================== */ + + for (col = 0 ; col < n_col ; col++) + { + Col [col].start = p [col] ; + Col [col].length = p [col+1] - p [col] ; + + if (Col [col].length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = Col [col].length ; + DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ; + return (FALSE) ; + } + + Col [col].shared1.thickness = 1 ; + Col [col].shared2.score = 0 ; + Col [col].shared3.prev = EMPTY ; + Col [col].shared4.degree_next = EMPTY ; + } + + /* p [0..n_col] no longer needed, used as "head" in subsequent routines */ + + /* === Scan columns, compute row degrees, and check row indices ========= */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].length = 0 ; + Row [row].shared2.mark = -1 ; + } + + for (col = 0 ; col < n_col ; col++) + { + last_row = -1 ; + + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + + while (cp < cp_end) + { + row = *cp++ ; + + /* make sure row indices within range */ + if (row < 0 || row >= n_row) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + stats [COLAMD_INFO3] = n_row ; + DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ; + return (FALSE) ; + } + + if (row <= last_row || Row [row].shared2.mark == col) + { + /* row index are unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col)); + } + + if (Row [row].shared2.mark != col) + { + Row [row].length++ ; + } + else + { + /* this is a repeated entry in the column, */ + /* it will be removed */ + Col [col].length-- ; + } + + /* mark the row as having been seen in this column */ + Row [row].shared2.mark = col ; + + last_row = row ; + } + } + + /* === Compute row pointers ============================================= */ + + /* row form of the matrix starts directly after the column */ + /* form of matrix in A */ + Row [0].start = p [n_col] ; + Row [0].shared1.p = Row [0].start ; + Row [0].shared2.mark = -1 ; + for (row = 1 ; row < n_row ; row++) + { + Row [row].start = Row [row-1].start + Row [row-1].length ; + Row [row].shared1.p = Row [row].start ; + Row [row].shared2.mark = -1 ; + } + + /* === Create row form ================================================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + /* if cols jumbled, watch for repeated row indices */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + row = *cp++ ; + if (Row [row].shared2.mark != col) + { + A [(Row [row].shared1.p)++] = col ; + Row [row].shared2.mark = col ; + } + } + } + } + else + { + /* if cols not jumbled, we don't need the mark (this is faster) */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + A [(Row [*cp++].shared1.p)++] = col ; + } + } + } + + /* === Clear the row marks and set row degrees ========================== */ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].shared2.mark = 0 ; + Row [row].shared1.degree = Row [row].length ; + } + + /* === See if we need to re-create columns ============================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ; + +#ifndef NDEBUG + /* make sure column lengths are correct */ + for (col = 0 ; col < n_col ; col++) + { + p [col] = Col [col].length ; + } + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + p [*rp++]-- ; + } + } + for (col = 0 ; col < n_col ; col++) + { + ASSERT (p [col] == 0) ; + } + /* now p is all zero (different than when debugging is turned off) */ +#endif /* NDEBUG */ + + /* === Compute col pointers ========================================= */ + + /* col form of the matrix starts at A [0]. */ + /* Note, we may have a gap between the col form and the row */ + /* form if there were duplicate entries, if so, it will be */ + /* removed upon the first garbage collection */ + Col [0].start = 0 ; + p [0] = Col [0].start ; + for (col = 1 ; col < n_col ; col++) + { + /* note that the lengths here are for pruned columns, i.e. */ + /* no duplicate row indices will exist for these columns */ + Col [col].start = Col [col-1].start + Col [col-1].length ; + p [col] = Col [col].start ; + } + + /* === Re-create col form =========================================== */ + + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + A [(p [*rp++])++] = row ; + } + } + } + + /* === Done. Matrix is not (or no longer) jumbled ====================== */ + + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === init_scoring ========================================================= */ +/* ========================================================================== */ + +/* + Kills dense or empty columns and rows, calculates an initial score for + each column, and places all columns in the degree lists. Not user-callable. +*/ + +PRIVATE void init_scoring +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows of A */ + int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + int A [], /* column form and row form of A */ + int head [], /* of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameters */ + int *p_n_row2, /* number of non-dense, non-empty rows */ + int *p_n_col2, /* number of non-dense, non-empty columns */ + int *p_max_deg /* maximum row degree */ +) +{ + /* === Local variables ================================================== */ + + int c ; /* a column index */ + int r, row ; /* a row index */ + int *cp ; /* a column pointer */ + int deg ; /* degree of a row or column */ + int *cp_end ; /* a pointer to the end of a column */ + int *new_cp ; /* new column pointer */ + int col_length ; /* length of pruned column */ + int score ; /* current column score */ + int n_col2 ; /* number of non-dense, non-empty columns */ + int n_row2 ; /* number of non-dense, non-empty rows */ + int dense_row_count ; /* remove rows with more entries than this */ + int dense_col_count ; /* remove cols with more entries than this */ + int min_score ; /* smallest column score */ + int max_deg ; /* maximum row degree */ + int next_col ; /* Used to add to degree list.*/ + +#ifndef NDEBUG + int debug_count ; /* debug only. */ +#endif /* NDEBUG */ + + /* === Extract knobs ==================================================== */ + + dense_row_count = MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ; + dense_col_count = MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ; + DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; + max_deg = 0 ; + n_col2 = n_col ; + n_row2 = n_row ; + + /* === Kill empty columns =============================================== */ + + /* Put the empty columns at the end in their natural order, so that LU */ + /* factorization can proceed as far as possible. */ + for (c = n_col-1 ; c >= 0 ; c--) + { + deg = Col [c].length ; + if (deg == 0) + { + /* this is a empty column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense columns =============================================== */ + + /* Put the dense columns at the end, in their natural order */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip any dead columns */ + if (COL_IS_DEAD (c)) + { + continue ; + } + deg = Col [c].length ; + if (deg > dense_col_count) + { + /* this is a dense column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + /* decrement the row degrees */ + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + Row [*cp++].shared1.degree-- ; + } + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense and empty rows ======================================== */ + + for (r = 0 ; r < n_row ; r++) + { + deg = Row [r].shared1.degree ; + ASSERT (deg >= 0 && deg <= n_col) ; + if (deg > dense_row_count || deg == 0) + { + /* kill a dense or empty row */ + KILL_ROW (r) ; + --n_row2 ; + } + else + { + /* keep track of max degree of remaining rows */ + max_deg = MAX (max_deg, deg) ; + } + } + DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ; + + /* === Compute initial column scores ==================================== */ + + /* At this point the row degrees are accurate. They reflect the number */ + /* of "live" (non-dense) columns in each row. No empty rows exist. */ + /* Some "live" columns may contain only dead rows, however. These are */ + /* pruned in the code below. */ + + /* now find the initial matlab score for each column */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip dead column */ + if (COL_IS_DEAD (c)) + { + continue ; + } + score = 0 ; + cp = &A [Col [c].start] ; + new_cp = cp ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + /* skip if dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + /* compact the column */ + *new_cp++ = row ; + /* add row's external degree */ + score += Row [row].shared1.degree - 1 ; + /* guard against integer overflow */ + score = MIN (score, n_col) ; + } + /* determine pruned column length */ + col_length = (int) (new_cp - &A [Col [c].start]) ; + if (col_length == 0) + { + /* a newly-made null column (all rows in this col are "dense" */ + /* and have already been killed) */ + DEBUG2 (("Newly null killed: %d\n", c)) ; + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + else + { + /* set column length and set score */ + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + Col [c].length = col_length ; + Col [c].shared2.score = score ; + } + } + DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n", + n_col-n_col2)) ; + + /* At this point, all empty rows and columns are dead. All live columns */ + /* are "clean" (containing no dead rows) and simplicial (no supercolumns */ + /* yet). Rows may contain dead columns, but all live rows contain at */ + /* least one live column. */ + +#ifndef NDEBUG + debug_structures (n_row, n_col, Row, Col, A, n_col2) ; +#endif /* NDEBUG */ + + /* === Initialize degree lists ========================================== */ + +#ifndef NDEBUG + debug_count = 0 ; +#endif /* NDEBUG */ + + /* clear the hash buckets */ + for (c = 0 ; c <= n_col ; c++) + { + head [c] = EMPTY ; + } + min_score = n_col ; + /* place in reverse order, so low column indices are at the front */ + /* of the lists. This is to encourage natural tie-breaking */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* only add principal columns to degree lists */ + if (COL_IS_ALIVE (c)) + { + DEBUG4 (("place %d score %d minscore %d ncol %d\n", + c, Col [c].shared2.score, min_score, n_col)) ; + + /* === Add columns score to DList =============================== */ + + score = Col [c].shared2.score ; + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + ASSERT (head [score] >= EMPTY) ; + + /* now add this column to dList at proper score location */ + next_col = head [score] ; + Col [c].shared3.prev = EMPTY ; + Col [c].shared4.degree_next = next_col ; + + /* if there already was a column with the same score, set its */ + /* previous pointer to this new column */ + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = c ; + } + head [score] = c ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, score) ; + +#ifndef NDEBUG + debug_count++ ; +#endif /* NDEBUG */ + + } + } + +#ifndef NDEBUG + DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n", + debug_count, n_col, n_col-debug_count)) ; + ASSERT (debug_count == n_col2) ; + debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ; +#endif /* NDEBUG */ + + /* === Return number of remaining columns, and max row degree =========== */ + + *p_n_col2 = n_col2 ; + *p_n_row2 = n_row2 ; + *p_max_deg = max_deg ; +} + + +/* ========================================================================== */ +/* === find_ordering ======================================================== */ +/* ========================================================================== */ + +/* + Order the principal columns of the supercolumn form of the matrix + (no supercolumns on input). Uses a minimum approximate column minimum + degree ordering method. Not user-callable. +*/ + +PRIVATE int find_ordering /* return the number of garbage collections */ +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows of A */ + int n_col, /* number of columns of A */ + int Alen, /* size of A, 2*nnz + n_col or larger */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + int A [], /* column form and row form of A */ + int head [], /* of size n_col+1 */ + int n_col2, /* Remaining columns to order */ + int max_deg, /* Maximum row degree */ + int pfree /* index of first free slot (2*nnz on entry) */ +) +{ + /* === Local variables ================================================== */ + + int k ; /* current pivot ordering step */ + int pivot_col ; /* current pivot column */ + int *cp ; /* a column pointer */ + int *rp ; /* a row pointer */ + int pivot_row ; /* current pivot row */ + int *new_cp ; /* modified column pointer */ + int *new_rp ; /* modified row pointer */ + int pivot_row_start ; /* pointer to start of pivot row */ + int pivot_row_degree ; /* number of columns in pivot row */ + int pivot_row_length ; /* number of supercolumns in pivot row */ + int pivot_col_score ; /* score of pivot column */ + int needed_memory ; /* free space needed for pivot row */ + int *cp_end ; /* pointer to the end of a column */ + int *rp_end ; /* pointer to the end of a row */ + int row ; /* a row index */ + int col ; /* a column index */ + int max_score ; /* maximum possible score */ + int cur_score ; /* score of current column */ + unsigned int hash ; /* hash value for supernode detection */ + int head_column ; /* head of hash bucket */ + int first_col ; /* first column in hash bucket */ + int tag_mark ; /* marker value for mark array */ + int row_mark ; /* Row [row].shared2.mark */ + int set_difference ; /* set difference size of row with pivot row */ + int min_score ; /* smallest column score */ + int col_thickness ; /* "thickness" (no. of columns in a supercol) */ + int max_mark ; /* maximum value of tag_mark */ + int pivot_col_thickness ; /* number of columns represented by pivot col */ + int prev_col ; /* Used by Dlist operations. */ + int next_col ; /* Used by Dlist operations. */ + int ngarbage ; /* number of garbage collections performed */ + +#ifndef NDEBUG + int debug_d ; /* debug loop counter */ + int debug_step = 0 ; /* debug loop counter */ +#endif /* NDEBUG */ + + /* === Initialization and clear mark ==================================== */ + + max_mark = INT_MAX - n_col ; /* INT_MAX defined in */ + tag_mark = clear_mark (n_row, Row) ; + min_score = 0 ; + ngarbage = 0 ; + DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ; + + /* === Order the columns ================================================ */ + + for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */) + { + +#ifndef NDEBUG + if (debug_step % 100 == 0) + { + DEBUG2 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + else + { + DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + debug_step++ ; + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + + /* === Select pivot column, and order it ============================ */ + + /* make sure degree list isn't empty */ + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (head [min_score] >= EMPTY) ; + +#ifndef NDEBUG + for (debug_d = 0 ; debug_d < min_score ; debug_d++) + { + ASSERT (head [debug_d] == EMPTY) ; + } +#endif /* NDEBUG */ + + /* get pivot column from head of minimum degree list */ + while (head [min_score] == EMPTY && min_score < n_col) + { + min_score++ ; + } + pivot_col = head [min_score] ; + ASSERT (pivot_col >= 0 && pivot_col <= n_col) ; + next_col = Col [pivot_col].shared4.degree_next ; + head [min_score] = next_col ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = EMPTY ; + } + + ASSERT (COL_IS_ALIVE (pivot_col)) ; + DEBUG3 (("Pivot col: %d\n", pivot_col)) ; + + /* remember score for defrag check */ + pivot_col_score = Col [pivot_col].shared2.score ; + + /* the pivot column is the kth column in the pivot order */ + Col [pivot_col].shared2.order = k ; + + /* increment order count by column thickness */ + pivot_col_thickness = Col [pivot_col].shared1.thickness ; + k += pivot_col_thickness ; + ASSERT (pivot_col_thickness > 0) ; + + /* === Garbage_collection, if necessary ============================= */ + + needed_memory = MIN (pivot_col_score, n_col - k) ; + if (pfree + needed_memory >= Alen) + { + pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; + ngarbage++ ; + /* after garbage collection we will have enough */ + ASSERT (pfree + needed_memory < Alen) ; + /* garbage collection has wiped out the Row[].shared2.mark array */ + tag_mark = clear_mark (n_row, Row) ; + +#ifndef NDEBUG + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + } + + /* === Compute pivot row pattern ==================================== */ + + /* get starting location for this new merged row */ + pivot_row_start = pfree ; + + /* initialize new row counts to zero */ + pivot_row_degree = 0 ; + + /* tag pivot column as having been visited so it isn't included */ + /* in merged pivot row */ + Col [pivot_col].shared1.thickness = -pivot_col_thickness ; + + /* pivot row is the union of all rows in the pivot column pattern */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ; + /* skip if row is dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + /* add the column, if alive and untagged */ + col_thickness = Col [col].shared1.thickness ; + if (col_thickness > 0 && COL_IS_ALIVE (col)) + { + /* tag column in pivot row */ + Col [col].shared1.thickness = -col_thickness ; + ASSERT (pfree < Alen) ; + /* place column in pivot row */ + A [pfree++] = col ; + pivot_row_degree += col_thickness ; + } + } + } + + /* clear tag on pivot column */ + Col [pivot_col].shared1.thickness = pivot_col_thickness ; + max_deg = MAX (max_deg, pivot_row_degree) ; + +#ifndef NDEBUG + DEBUG3 (("check2\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Kill all rows used to construct pivot row ==================== */ + + /* also kill pivot row, temporarily */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* may be killing an already dead row */ + row = *cp++ ; + DEBUG3 (("Kill row in pivot col: %d\n", row)) ; + KILL_ROW (row) ; + } + + /* === Select a row index to use as the new pivot row =============== */ + + pivot_row_length = pfree - pivot_row_start ; + if (pivot_row_length > 0) + { + /* pick the "pivot" row arbitrarily (first row in col) */ + pivot_row = A [Col [pivot_col].start] ; + DEBUG3 (("Pivotal row is %d\n", pivot_row)) ; + } + else + { + /* there is no pivot row, since it is of zero length */ + pivot_row = EMPTY ; + ASSERT (pivot_row_length == 0) ; + } + ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ; + + /* === Approximate degree computation =============================== */ + + /* Here begins the computation of the approximate degree. The column */ + /* score is the sum of the pivot row "length", plus the size of the */ + /* set differences of each row in the column minus the pattern of the */ + /* pivot row itself. The column ("thickness") itself is also */ + /* excluded from the column score (we thus use an approximate */ + /* external degree). */ + + /* The time taken by the following code (compute set differences, and */ + /* add them up) is proportional to the size of the data structure */ + /* being scanned - that is, the sum of the sizes of each column in */ + /* the pivot row. Thus, the amortized time to compute a column score */ + /* is proportional to the size of that column (where size, in this */ + /* context, is the column "length", or the number of row indices */ + /* in that column). The number of row indices in a column is */ + /* monotonically non-decreasing, from the length of the original */ + /* column on input to colamd. */ + + /* === Compute set differences ====================================== */ + + DEBUG3 (("** Computing set differences phase. **\n")) ; + + /* pivot row is currently dead - it will be revived later. */ + + DEBUG3 (("Pivot row: ")) ; + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + DEBUG3 (("Col: %d\n", col)) ; + + /* clear tags used to construct pivot row pattern */ + col_thickness = -Col [col].shared1.thickness ; + ASSERT (col_thickness > 0) ; + Col [col].shared1.thickness = col_thickness ; + + /* === Remove column from degree list =========================== */ + + cur_score = Col [col].shared2.score ; + prev_col = Col [col].shared3.prev ; + next_col = Col [col].shared4.degree_next ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (cur_score >= EMPTY) ; + if (prev_col == EMPTY) + { + head [cur_score] = next_col ; + } + else + { + Col [prev_col].shared4.degree_next = next_col ; + } + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = prev_col ; + } + + /* === Scan the column ========================================== */ + + cp = &A [Col [col].start] ; + cp_end = cp + Col [col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + continue ; + } + ASSERT (row != pivot_row) ; + set_difference = row_mark - tag_mark ; + /* check if the row has been seen yet */ + if (set_difference < 0) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + set_difference = Row [row].shared1.degree ; + } + /* subtract column thickness from this row's set difference */ + set_difference -= col_thickness ; + ASSERT (set_difference >= 0) ; + /* absorb this row if the set difference becomes zero */ + if (set_difference == 0) + { + DEBUG3 (("aggressive absorption. Row: %d\n", row)) ; + KILL_ROW (row) ; + } + else + { + /* save the new mark */ + Row [row].shared2.mark = set_difference + tag_mark ; + } + } + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k-pivot_row_degree, max_deg) ; +#endif /* NDEBUG */ + + /* === Add up set differences for each column ======================= */ + + DEBUG3 (("** Adding set differences phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + hash = 0 ; + cur_score = 0 ; + cp = &A [Col [col].start] ; + /* compact the column */ + new_cp = cp ; + cp_end = cp + Col [col].length ; + + DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ; + + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + ASSERT(row >= 0 && row < n_row) ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + continue ; + } + ASSERT (row_mark > tag_mark) ; + /* compact the column */ + *new_cp++ = row ; + /* compute hash function */ + hash += row ; + /* add set difference */ + cur_score += row_mark - tag_mark ; + /* integer overflow... */ + cur_score = MIN (cur_score, n_col) ; + } + + /* recompute the column's length */ + Col [col].length = (int) (new_cp - &A [Col [col].start]) ; + + /* === Further mass elimination ================================= */ + + if (Col [col].length == 0) + { + DEBUG4 (("further mass elimination. Col: %d\n", col)) ; + /* nothing left but the pivot row in this column */ + KILL_PRINCIPAL_COL (col) ; + pivot_row_degree -= Col [col].shared1.thickness ; + ASSERT (pivot_row_degree >= 0) ; + /* order it */ + Col [col].shared2.order = k ; + /* increment order count by column thickness */ + k += Col [col].shared1.thickness ; + } + else + { + /* === Prepare for supercolumn detection ==================== */ + + DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ; + + /* save score so far */ + Col [col].shared2.score = cur_score ; + + /* add column to hash table, for supercolumn detection */ + hash %= n_col + 1 ; + + DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ; + ASSERT (hash <= n_col) ; + + head_column = head [hash] ; + if (head_column > EMPTY) + { + /* degree list "hash" is non-empty, use prev (shared3) of */ + /* first column in degree list as head of hash bucket */ + first_col = Col [head_column].shared3.headhash ; + Col [head_column].shared3.headhash = col ; + } + else + { + /* degree list "hash" is empty, use head as hash bucket */ + first_col = - (head_column + 2) ; + head [hash] = - (col + 2) ; + } + Col [col].shared4.hash_next = first_col ; + + /* save hash function in Col [col].shared3.hash */ + Col [col].shared3.hash = (int) hash ; + ASSERT (COL_IS_ALIVE (col)) ; + } + } + + /* The approximate external column degree is now computed. */ + + /* === Supercolumn detection ======================================== */ + + DEBUG3 (("** Supercolumn detection phase. **\n")) ; + + detect_super_cols ( + +#ifndef NDEBUG + n_col, Row, +#endif /* NDEBUG */ + + Col, A, head, pivot_row_start, pivot_row_length) ; + + /* === Kill the pivotal column ====================================== */ + + KILL_PRINCIPAL_COL (pivot_col) ; + + /* === Clear mark =================================================== */ + + tag_mark += (max_deg + 1) ; + if (tag_mark >= max_mark) + { + DEBUG2 (("clearing tag_mark\n")) ; + tag_mark = clear_mark (n_row, Row) ; + } + +#ifndef NDEBUG + DEBUG3 (("check3\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Finalize the new pivot row, and column scores ================ */ + + DEBUG3 (("** Finalize scores phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + /* compact the pivot row */ + new_rp = rp ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + /* skip dead columns */ + if (COL_IS_DEAD (col)) + { + continue ; + } + *new_rp++ = col ; + /* add new pivot row to column */ + A [Col [col].start + (Col [col].length++)] = pivot_row ; + + /* retrieve score so far and add on pivot row's degree. */ + /* (we wait until here for this in case the pivot */ + /* row's degree was reduced due to mass elimination). */ + cur_score = Col [col].shared2.score + pivot_row_degree ; + + /* calculate the max possible score as the number of */ + /* external columns minus the 'k' value minus the */ + /* columns thickness */ + max_score = n_col - k - Col [col].shared1.thickness ; + + /* make the score the external degree of the union-of-rows */ + cur_score -= Col [col].shared1.thickness ; + + /* make sure score is less or equal than the max score */ + cur_score = MIN (cur_score, max_score) ; + ASSERT (cur_score >= 0) ; + + /* store updated score */ + Col [col].shared2.score = cur_score ; + + /* === Place column back in degree list ========================= */ + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (head [cur_score] >= EMPTY) ; + next_col = head [cur_score] ; + Col [col].shared4.degree_next = next_col ; + Col [col].shared3.prev = EMPTY ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = col ; + } + head [cur_score] = col ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, cur_score) ; + + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; +#endif /* NDEBUG */ + + /* === Resurrect the new pivot row ================================== */ + + if (pivot_row_degree > 0) + { + /* update pivot row length to reflect any cols that were killed */ + /* during super-col detection and mass elimination */ + Row [pivot_row].start = pivot_row_start ; + Row [pivot_row].length = (int) (new_rp - &A[pivot_row_start]) ; + Row [pivot_row].shared1.degree = pivot_row_degree ; + Row [pivot_row].shared2.mark = 0 ; + /* pivot row is no longer dead */ + } + } + + /* === All principal columns have now been ordered ====================== */ + + return (ngarbage) ; +} + + +/* ========================================================================== */ +/* === order_children ======================================================= */ +/* ========================================================================== */ + +/* + The find_ordering routine has ordered all of the principal columns (the + representatives of the supercolumns). The non-principal columns have not + yet been ordered. This routine orders those columns by walking up the + parent tree (a column is a child of the column which absorbed it). The + final permutation vector is then placed in p [0 ... n_col-1], with p [0] + being the first column, and p [n_col-1] being the last. It doesn't look + like it at first glance, but be assured that this routine takes time linear + in the number of columns. Although not immediately obvious, the time + taken by this routine is O (n_col), that is, linear in the number of + columns. Not user-callable. +*/ + +PRIVATE void order_children +( + /* === Parameters ======================================================= */ + + int n_col, /* number of columns of A */ + Colamd_Col Col [], /* of size n_col+1 */ + int p [] /* p [0 ... n_col-1] is the column permutation*/ +) +{ + /* === Local variables ================================================== */ + + int i ; /* loop counter for all columns */ + int c ; /* column index */ + int parent ; /* index of column's parent */ + int order ; /* column's order */ + + /* === Order each non-principal column ================================== */ + + for (i = 0 ; i < n_col ; i++) + { + /* find an un-ordered non-principal column */ + ASSERT (COL_IS_DEAD (i)) ; + if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY) + { + parent = i ; + /* once found, find its principal parent */ + do + { + parent = Col [parent].shared1.parent ; + } while (!COL_IS_DEAD_PRINCIPAL (parent)) ; + + /* now, order all un-ordered non-principal columns along path */ + /* to this parent. collapse tree at the same time */ + c = i ; + /* get order of parent */ + order = Col [parent].shared2.order ; + + do + { + ASSERT (Col [c].shared2.order == EMPTY) ; + + /* order this column */ + Col [c].shared2.order = order++ ; + /* collaps tree */ + Col [c].shared1.parent = parent ; + + /* get immediate parent of this column */ + c = Col [c].shared1.parent ; + + /* continue until we hit an ordered column. There are */ + /* guarranteed not to be anymore unordered columns */ + /* above an ordered column */ + } while (Col [c].shared2.order == EMPTY) ; + + /* re-order the super_col parent to largest order for this group */ + Col [parent].shared2.order = order ; + } + } + + /* === Generate the permutation ========================================= */ + + for (c = 0 ; c < n_col ; c++) + { + p [Col [c].shared2.order] = c ; + } +} + + +/* ========================================================================== */ +/* === detect_super_cols ==================================================== */ +/* ========================================================================== */ + +/* + Detects supercolumns by finding matches between columns in the hash buckets. + Check amongst columns in the set A [row_start ... row_start + row_length-1]. + The columns under consideration are currently *not* in the degree lists, + and have already been placed in the hash buckets. + + The hash bucket for columns whose hash function is equal to h is stored + as follows: + + if head [h] is >= 0, then head [h] contains a degree list, so: + + head [h] is the first column in degree bucket h. + Col [head [h]].headhash gives the first column in hash bucket h. + + otherwise, the degree list is empty, and: + + -(head [h] + 2) is the first column in hash bucket h. + + For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous + column" pointer. Col [c].shared3.hash is used instead as the hash number + for that column. The value of Col [c].shared4.hash_next is the next column + in the same hash bucket. + + Assuming no, or "few" hash collisions, the time taken by this routine is + linear in the sum of the sizes (lengths) of each column whose score has + just been computed in the approximate degree computation. + Not user-callable. +*/ + +PRIVATE void detect_super_cols +( + /* === Parameters ======================================================= */ + +#ifndef NDEBUG + /* these two parameters are only needed when debugging is enabled: */ + int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ +#endif /* NDEBUG */ + + Colamd_Col Col [], /* of size n_col+1 */ + int A [], /* row indices of A */ + int head [], /* head of degree lists and hash buckets */ + int row_start, /* pointer to set of columns to check */ + int row_length /* number of columns to check */ +) +{ + /* === Local variables ================================================== */ + + int hash ; /* hash value for a column */ + int *rp ; /* pointer to a row */ + int c ; /* a column index */ + int super_c ; /* column index of the column to absorb into */ + int *cp1 ; /* column pointer for column super_c */ + int *cp2 ; /* column pointer for column c */ + int length ; /* length of column super_c */ + int prev_c ; /* column preceding c in hash bucket */ + int i ; /* loop counter */ + int *rp_end ; /* pointer to the end of the row */ + int col ; /* a column index in the row to check */ + int head_column ; /* first column in hash bucket or degree list */ + int first_col ; /* first column in hash bucket */ + + /* === Consider each column in the row ================================== */ + + rp = &A [row_start] ; + rp_end = rp + row_length ; + while (rp < rp_end) + { + col = *rp++ ; + if (COL_IS_DEAD (col)) + { + continue ; + } + + /* get hash number for this column */ + hash = Col [col].shared3.hash ; + ASSERT (hash <= n_col) ; + + /* === Get the first column in this hash bucket ===================== */ + + head_column = head [hash] ; + if (head_column > EMPTY) + { + first_col = Col [head_column].shared3.headhash ; + } + else + { + first_col = - (head_column + 2) ; + } + + /* === Consider each column in the hash bucket ====================== */ + + for (super_c = first_col ; super_c != EMPTY ; + super_c = Col [super_c].shared4.hash_next) + { + ASSERT (COL_IS_ALIVE (super_c)) ; + ASSERT (Col [super_c].shared3.hash == hash) ; + length = Col [super_c].length ; + + /* prev_c is the column preceding column c in the hash bucket */ + prev_c = super_c ; + + /* === Compare super_c with all columns after it ================ */ + + for (c = Col [super_c].shared4.hash_next ; + c != EMPTY ; c = Col [c].shared4.hash_next) + { + ASSERT (c != super_c) ; + ASSERT (COL_IS_ALIVE (c)) ; + ASSERT (Col [c].shared3.hash == hash) ; + + /* not identical if lengths or scores are different */ + if (Col [c].length != length || + Col [c].shared2.score != Col [super_c].shared2.score) + { + prev_c = c ; + continue ; + } + + /* compare the two columns */ + cp1 = &A [Col [super_c].start] ; + cp2 = &A [Col [c].start] ; + + for (i = 0 ; i < length ; i++) + { + /* the columns are "clean" (no dead rows) */ + ASSERT (ROW_IS_ALIVE (*cp1)) ; + ASSERT (ROW_IS_ALIVE (*cp2)) ; + /* row indices will same order for both supercols, */ + /* no gather scatter nessasary */ + if (*cp1++ != *cp2++) + { + break ; + } + } + + /* the two columns are different if the for-loop "broke" */ + if (i != length) + { + prev_c = c ; + continue ; + } + + /* === Got it! two columns are identical =================== */ + + ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ; + + Col [super_c].shared1.thickness += Col [c].shared1.thickness ; + Col [c].shared1.parent = super_c ; + KILL_NON_PRINCIPAL_COL (c) ; + /* order c later, in order_children() */ + Col [c].shared2.order = EMPTY ; + /* remove c from hash bucket */ + Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ; + } + } + + /* === Empty this hash bucket ======================================= */ + + if (head_column > EMPTY) + { + /* corresponding degree list "hash" is not empty */ + Col [head_column].shared3.headhash = EMPTY ; + } + else + { + /* corresponding degree list "hash" is empty */ + head [hash] = EMPTY ; + } + } +} + + +/* ========================================================================== */ +/* === garbage_collection =================================================== */ +/* ========================================================================== */ + +/* + Defragments and compacts columns and rows in the workspace A. Used when + all avaliable memory has been used while performing row merging. Returns + the index of the first free position in A, after garbage collection. The + time taken by this routine is linear is the size of the array A, which is + itself linear in the number of nonzeros in the input matrix. + Not user-callable. +*/ + +PRIVATE int garbage_collection /* returns the new value of pfree */ +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows */ + int n_col, /* number of columns */ + Colamd_Row Row [], /* row info */ + Colamd_Col Col [], /* column info */ + int A [], /* A [0 ... Alen-1] holds the matrix */ + int *pfree /* &A [0] ... pfree is in use */ +) +{ + /* === Local variables ================================================== */ + + int *psrc ; /* source pointer */ + int *pdest ; /* destination pointer */ + int j ; /* counter */ + int r ; /* a row index */ + int c ; /* a column index */ + int length ; /* length of a row or column */ + +#ifndef NDEBUG + int debug_rows ; + DEBUG2 (("Defrag..\n")) ; + for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; + debug_rows = 0 ; +#endif /* NDEBUG */ + + /* === Defragment the columns =========================================== */ + + pdest = &A[0] ; + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + psrc = &A [Col [c].start] ; + + /* move and compact the column */ + ASSERT (pdest <= psrc) ; + Col [c].start = (int) (pdest - &A [0]) ; + length = Col [c].length ; + for (j = 0 ; j < length ; j++) + { + r = *psrc++ ; + if (ROW_IS_ALIVE (r)) + { + *pdest++ = r ; + } + } + Col [c].length = (int) (pdest - &A [Col [c].start]) ; + } + } + + /* === Prepare to defragment the rows =================================== */ + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + if (Row [r].length == 0) + { + /* this row is of zero length. cannot compact it, so kill it */ + DEBUG3 (("Defrag row kill\n")) ; + KILL_ROW (r) ; + } + else + { + /* save first column index in Row [r].shared2.first_column */ + psrc = &A [Row [r].start] ; + Row [r].shared2.first_column = *psrc ; + ASSERT (ROW_IS_ALIVE (r)) ; + /* flag the start of the row with the one's complement of row */ + *psrc = ONES_COMPLEMENT (r) ; + +#ifndef NDEBUG + debug_rows++ ; +#endif /* NDEBUG */ + + } + } + } + + /* === Defragment the rows ============================================== */ + + psrc = pdest ; + while (psrc < pfree) + { + /* find a negative number ... the start of a row */ + if (*psrc++ < 0) + { + psrc-- ; + /* get the row index */ + r = ONES_COMPLEMENT (*psrc) ; + ASSERT (r >= 0 && r < n_row) ; + /* restore first column index */ + *psrc = Row [r].shared2.first_column ; + ASSERT (ROW_IS_ALIVE (r)) ; + + /* move and compact the row */ + ASSERT (pdest <= psrc) ; + Row [r].start = (int) (pdest - &A [0]) ; + length = Row [r].length ; + for (j = 0 ; j < length ; j++) + { + c = *psrc++ ; + if (COL_IS_ALIVE (c)) + { + *pdest++ = c ; + } + } + Row [r].length = (int) (pdest - &A [Row [r].start]) ; + +#ifndef NDEBUG + debug_rows-- ; +#endif /* NDEBUG */ + + } + } + /* ensure we found all the rows */ + ASSERT (debug_rows == 0) ; + + /* === Return the new value of pfree ==================================== */ + + return ((int) (pdest - &A [0])) ; +} + + +/* ========================================================================== */ +/* === clear_mark =========================================================== */ +/* ========================================================================== */ + +/* + Clears the Row [].shared2.mark array, and returns the new tag_mark. + Return value is the new tag_mark. Not user-callable. +*/ + +PRIVATE int clear_mark /* return the new value for tag_mark */ +( + /* === Parameters ======================================================= */ + + int n_row, /* number of rows in A */ + Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */ +) +{ + /* === Local variables ================================================== */ + + int r ; + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + Row [r].shared2.mark = 0 ; + } + } + return (1) ; +} + + +/* ========================================================================== */ +/* === print_report ========================================================= */ +/* ========================================================================== */ + +PRIVATE void print_report +( + char *method, + int stats [COLAMD_STATS] +) +{ + + int i1, i2, i3 ; + + if (!stats) + { + PRINTF ("%s: No statistics available.\n", method) ; + return ; + } + + i1 = stats [COLAMD_INFO1] ; + i2 = stats [COLAMD_INFO2] ; + i3 = stats [COLAMD_INFO3] ; + + if (stats [COLAMD_STATUS] >= 0) + { + PRINTF ("%s: OK. ", method) ; + } + else + { + PRINTF ("%s: ERROR. ", method) ; + } + + switch (stats [COLAMD_STATUS]) + { + + case COLAMD_OK_BUT_JUMBLED: + + PRINTF ("Matrix has unsorted or duplicate row indices.\n") ; + + PRINTF ("%s: number of duplicate or out-of-order row indices: %d\n", + method, i3) ; + + PRINTF ("%s: last seen duplicate or out-of-order row index: %d\n", + method, INDEX (i2)) ; + + PRINTF ("%s: last seen in column: %d", + method, INDEX (i1)) ; + + /* no break - fall through to next case instead */ + + case COLAMD_OK: + + PRINTF ("\n") ; + + PRINTF ("%s: number of dense or empty rows ignored: %d\n", + method, stats [COLAMD_DENSE_ROW]) ; + + PRINTF ("%s: number of dense or empty columns ignored: %d\n", + method, stats [COLAMD_DENSE_COL]) ; + + PRINTF ("%s: number of garbage collections performed: %d\n", + method, stats [COLAMD_DEFRAG_COUNT]) ; + break ; + + case COLAMD_ERROR_A_not_present: + + PRINTF ("Array A (row indices of matrix) not present.\n") ; + break ; + + case COLAMD_ERROR_p_not_present: + + PRINTF ("Array p (column pointers for matrix) not present.\n") ; + break ; + + case COLAMD_ERROR_nrow_negative: + + PRINTF ("Invalid number of rows (%d).\n", i1) ; + break ; + + case COLAMD_ERROR_ncol_negative: + + PRINTF ("Invalid number of columns (%d).\n", i1) ; + break ; + + case COLAMD_ERROR_nnz_negative: + + PRINTF ("Invalid number of nonzero entries (%d).\n", i1) ; + break ; + + case COLAMD_ERROR_p0_nonzero: + + PRINTF ("Invalid column pointer, p [0] = %d, must be zero.\n", i1) ; + break ; + + case COLAMD_ERROR_A_too_small: + + PRINTF ("Array A too small.\n") ; + PRINTF (" Need Alen >= %d, but given only Alen = %d.\n", + i1, i2) ; + break ; + + case COLAMD_ERROR_col_length_negative: + + PRINTF + ("Column %d has a negative number of nonzero entries (%d).\n", + INDEX (i1), i2) ; + break ; + + case COLAMD_ERROR_row_index_out_of_bounds: + + PRINTF + ("Row index (row %d) out of bounds (%d to %d) in column %d.\n", + INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1)) ; + break ; + + case COLAMD_ERROR_out_of_memory: + + PRINTF ("Out of memory.\n") ; + break ; + + case COLAMD_ERROR_internal_error: + + /* if this happens, there is a bug in the code */ + PRINTF + ("Internal error! Please contact authors (davis@cise.ufl.edu).\n") ; + break ; + } +} + + + + +/* ========================================================================== */ +/* === colamd debugging routines ============================================ */ +/* ========================================================================== */ + +/* When debugging is disabled, the remainder of this file is ignored. */ + +#ifndef NDEBUG + + +/* ========================================================================== */ +/* === debug_structures ===================================================== */ +/* ========================================================================== */ + +/* + At this point, all empty rows and columns are dead. All live columns + are "clean" (containing no dead rows) and simplicial (no supercolumns + yet). Rows may contain dead columns, but all live rows contain at + least one live column. +*/ + +PRIVATE void debug_structures +( + /* === Parameters ======================================================= */ + + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [], + int n_col2 +) +{ + /* === Local variables ================================================== */ + + int i ; + int c ; + int *cp ; + int *cp_end ; + int len ; + int score ; + int r ; + int *rp ; + int *rp_end ; + int deg ; + + /* === Check A, Row, and Col ============================================ */ + + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + len = Col [c].length ; + score = Col [c].shared2.score ; + DEBUG4 (("initial live col %5d %5d %5d\n", c, len, score)) ; + ASSERT (len > 0) ; + ASSERT (score >= 0) ; + ASSERT (Col [c].shared1.thickness == 1) ; + cp = &A [Col [c].start] ; + cp_end = cp + len ; + while (cp < cp_end) + { + r = *cp++ ; + ASSERT (ROW_IS_ALIVE (r)) ; + } + } + else + { + i = Col [c].shared2.order ; + ASSERT (i >= n_col2 && i < n_col) ; + } + } + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + i = 0 ; + len = Row [r].length ; + deg = Row [r].shared1.degree ; + ASSERT (len > 0) ; + ASSERT (deg > 0) ; + rp = &A [Row [r].start] ; + rp_end = rp + len ; + while (rp < rp_end) + { + c = *rp++ ; + if (COL_IS_ALIVE (c)) + { + i++ ; + } + } + ASSERT (i > 0) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_deg_lists ====================================================== */ +/* ========================================================================== */ + +/* + Prints the contents of the degree lists. Counts the number of columns + in the degree list and compares it to the total it should have. Also + checks the row degrees. +*/ + +PRIVATE void debug_deg_lists +( + /* === Parameters ======================================================= */ + + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int head [], + int min_score, + int should, + int max_deg +) +{ + /* === Local variables ================================================== */ + + int deg ; + int col ; + int have ; + int row ; + + /* === Check the degree lists =========================================== */ + + if (n_col > 10000 && colamd_debug <= 0) + { + return ; + } + have = 0 ; + DEBUG4 (("Degree lists: %d\n", min_score)) ; + for (deg = 0 ; deg <= n_col ; deg++) + { + col = head [deg] ; + if (col == EMPTY) + { + continue ; + } + DEBUG4 (("%d:", deg)) ; + while (col != EMPTY) + { + DEBUG4 ((" %d", col)) ; + have += Col [col].shared1.thickness ; + ASSERT (COL_IS_ALIVE (col)) ; + col = Col [col].shared4.degree_next ; + } + DEBUG4 (("\n")) ; + } + DEBUG4 (("should %d have %d\n", should, have)) ; + ASSERT (should == have) ; + + /* === Check the row degrees ============================================ */ + + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (row = 0 ; row < n_row ; row++) + { + if (ROW_IS_ALIVE (row)) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_mark =========================================================== */ +/* ========================================================================== */ + +/* + Ensures that the tag_mark is less that the maximum and also ensures that + each entry in the mark array is less than the tag mark. +*/ + +PRIVATE void debug_mark +( + /* === Parameters ======================================================= */ + + int n_row, + Colamd_Row Row [], + int tag_mark, + int max_mark +) +{ + /* === Local variables ================================================== */ + + int r ; + + /* === Check the Row marks ============================================== */ + + ASSERT (tag_mark > 0 && tag_mark <= max_mark) ; + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (r = 0 ; r < n_row ; r++) + { + ASSERT (Row [r].shared2.mark < tag_mark) ; + } +} + + +/* ========================================================================== */ +/* === debug_matrix ========================================================= */ +/* ========================================================================== */ + +/* + Prints out the contents of the columns and the rows. +*/ + +PRIVATE void debug_matrix +( + /* === Parameters ======================================================= */ + + int n_row, + int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + int A [] +) +{ + /* === Local variables ================================================== */ + + int r ; + int c ; + int *rp ; + int *rp_end ; + int *cp ; + int *cp_end ; + + /* === Dump the rows and columns of the matrix ========================== */ + + if (colamd_debug < 3) + { + return ; + } + DEBUG3 (("DUMP MATRIX:\n")) ; + for (r = 0 ; r < n_row ; r++) + { + DEBUG3 (("Row %d alive? %d\n", r, ROW_IS_ALIVE (r))) ; + if (ROW_IS_DEAD (r)) + { + continue ; + } + DEBUG3 (("start %d length %d degree %d\n", + Row [r].start, Row [r].length, Row [r].shared1.degree)) ; + rp = &A [Row [r].start] ; + rp_end = rp + Row [r].length ; + while (rp < rp_end) + { + c = *rp++ ; + DEBUG4 ((" %d col %d\n", COL_IS_ALIVE (c), c)) ; + } + } + + for (c = 0 ; c < n_col ; c++) + { + DEBUG3 (("Col %d alive? %d\n", c, COL_IS_ALIVE (c))) ; + if (COL_IS_DEAD (c)) + { + continue ; + } + DEBUG3 (("start %d length %d shared1 %d shared2 %d\n", + Col [c].start, Col [c].length, + Col [c].shared1.thickness, Col [c].shared2.score)) ; + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + r = *cp++ ; + DEBUG4 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ; + } + } +} + +PRIVATE void colamd_get_debug +( + char *method +) +{ + colamd_debug = 0 ; /* no debug printing */ + + /* get "D" environment variable, which gives the debug printing level */ + if (getenv ("D")) + { + colamd_debug = atoi (getenv ("D")) ; + } + + DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", + method, colamd_debug)) ; +} + +#endif /* NDEBUG */ + diff --git a/liboctave/COLAMD/colamd.h b/liboctave/COLAMD/colamd.h new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd.h @@ -0,0 +1,246 @@ +/* ========================================================================== */ +/* === colamd/symamd prototypes and definitions ============================= */ +/* ========================================================================== */ + +/* + You must include this file (colamd.h) in any routine that uses colamd, + symamd, or the related macros and definitions. + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Notice: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use, copy, modify, and/or distribute + this program, provided that the Copyright, this License, and the + Availability of the original version is retained on all copies and made + accessible to the end-user of any code or package that includes COLAMD + or any modified version of COLAMD. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h + file. It is required by the colamd.c, colamdmex.c, and symamdmex.c + files, and by any C code that calls the routines whose prototypes are + listed below, or that uses the colamd/symamd definitions listed below. + +*/ + +#ifndef COLAMD_H +#define COLAMD_H + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include + +/* ========================================================================== */ +/* === Knob and statistics definitions ====================================== */ +/* ========================================================================== */ + +/* size of the knobs [ ] array. Only knobs [0..1] are currently used. */ +#define COLAMD_KNOBS 20 + +/* number of output statistics. Only stats [0..6] are currently used. */ +#define COLAMD_STATS 20 + +/* knobs [0] and stats [0]: dense row knob and output statistic. */ +#define COLAMD_DENSE_ROW 0 + +/* knobs [1] and stats [1]: dense column knob and output statistic. */ +#define COLAMD_DENSE_COL 1 + +/* stats [2]: memory defragmentation count output statistic */ +#define COLAMD_DEFRAG_COUNT 2 + +/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */ +#define COLAMD_STATUS 3 + +/* stats [4..6]: error info, or info on jumbled columns */ +#define COLAMD_INFO1 4 +#define COLAMD_INFO2 5 +#define COLAMD_INFO3 6 + +/* error codes returned in stats [3]: */ +#define COLAMD_OK (0) +#define COLAMD_OK_BUT_JUMBLED (1) +#define COLAMD_ERROR_A_not_present (-1) +#define COLAMD_ERROR_p_not_present (-2) +#define COLAMD_ERROR_nrow_negative (-3) +#define COLAMD_ERROR_ncol_negative (-4) +#define COLAMD_ERROR_nnz_negative (-5) +#define COLAMD_ERROR_p0_nonzero (-6) +#define COLAMD_ERROR_A_too_small (-7) +#define COLAMD_ERROR_col_length_negative (-8) +#define COLAMD_ERROR_row_index_out_of_bounds (-9) +#define COLAMD_ERROR_out_of_memory (-10) +#define COLAMD_ERROR_internal_error (-999) + +/* ========================================================================== */ +/* === Row and Column structures ============================================ */ +/* ========================================================================== */ + +/* User code that makes use of the colamd/symamd routines need not directly */ +/* reference these structures. They are used only for the COLAMD_RECOMMENDED */ +/* macro. */ + +typedef struct Colamd_Col_struct +{ + int start ; /* index for A of first row in this column, or DEAD */ + /* if column is dead */ + int length ; /* number of rows in this column */ + union + { + int thickness ; /* number of original columns represented by this */ + /* col, if the column is alive */ + int parent ; /* parent in parent tree super-column structure, if */ + /* the column is dead */ + } shared1 ; + union + { + int score ; /* the score used to maintain heap, if col is alive */ + int order ; /* pivot ordering of this column, if col is dead */ + } shared2 ; + union + { + int headhash ; /* head of a hash bucket, if col is at the head of */ + /* a degree list */ + int hash ; /* hash value, if col is not in a degree list */ + int prev ; /* previous column in degree list, if col is in a */ + /* degree list (but not at the head of a degree list) */ + } shared3 ; + union + { + int degree_next ; /* next column, if col is in a degree list */ + int hash_next ; /* next column, if col is in a hash list */ + } shared4 ; + +} Colamd_Col ; + +typedef struct Colamd_Row_struct +{ + int start ; /* index for A of first col in this row */ + int length ; /* number of principal columns in this row */ + union + { + int degree ; /* number of principal & non-principal columns in row */ + int p ; /* used as a row pointer in init_rows_cols () */ + } shared1 ; + union + { + int mark ; /* for computing set differences and marking dead rows*/ + int first_column ;/* first column in row (used in garbage collection) */ + } shared2 ; + +} Colamd_Row ; + +/* ========================================================================== */ +/* === Colamd recommended memory size ======================================= */ +/* ========================================================================== */ + +/* + The recommended length Alen of the array A passed to colamd is given by + the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any + argument is negative. 2*nnz space is required for the row and column + indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is + required for the Col and Row arrays, respectively, which are internal to + colamd. An additional n_col space is the minimal amount of "elbow room", + and nnz/5 more space is recommended for run time efficiency. + + This macro is not needed when using symamd. + + Explicit typecast to int added Sept. 23, 2002, COLAMD version 2.2, to avoid + gcc -pedantic warning messages. +*/ + +#define COLAMD_C(n_col) ((int) (((n_col) + 1) * sizeof (Colamd_Col) / sizeof (int))) +#define COLAMD_R(n_row) ((int) (((n_row) + 1) * sizeof (Colamd_Row) / sizeof (int))) + +#define COLAMD_RECOMMENDED(nnz, n_row, n_col) \ +( \ +((nnz) < 0 || (n_row) < 0 || (n_col) < 0) \ +? \ + (-1) \ +: \ + (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \ +) + +/* ========================================================================== */ +/* === Prototypes of user-callable routines ================================= */ +/* ========================================================================== */ + +int colamd_recommended /* returns recommended value of Alen, */ + /* or (-1) if input arguments are erroneous */ +( + int nnz, /* nonzeros in A */ + int n_row, /* number of rows in A */ + int n_col /* number of columns in A */ +) ; + +void colamd_set_defaults /* sets default parameters */ +( /* knobs argument is modified on output */ + double knobs [COLAMD_KNOBS] /* parameter settings for colamd */ +) ; + +int colamd /* returns (1) if successful, (0) otherwise*/ +( /* A and p arguments are modified on output */ + int n_row, /* number of rows in A */ + int n_col, /* number of columns in A */ + int Alen, /* size of the array A */ + int A [], /* row indices of A, of size Alen */ + int p [], /* column pointers of A, of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameter settings for colamd */ + int stats [COLAMD_STATS] /* colamd output statistics and error codes */ +) ; + +int symamd /* return (1) if OK, (0) otherwise */ +( + int n, /* number of rows and columns of A */ + int A [], /* row indices of A */ + int p [], /* column pointers of A */ + int perm [], /* output permutation, size n_col+1 */ + double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ + int stats [COLAMD_STATS], /* output statistics and error codes */ + void * (*allocate) (size_t, size_t), + /* pointer to calloc (ANSI C) or */ + /* mxCalloc (for MATLAB mexFunction) */ + void (*release) (void *) + /* pointer to free (ANSI C) or */ + /* mxFree (for MATLAB mexFunction) */ +) ; + +void colamd_report +( + int stats [COLAMD_STATS] +) ; + +void symamd_report +( + int stats [COLAMD_STATS] +) ; + +#endif /* COLAMD_H */ diff --git a/liboctave/COLAMD/colamd.m b/liboctave/COLAMD/colamd.m new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd.m @@ -0,0 +1,109 @@ +function [p,stats] = colamd (S, knobs) +%COLAMD Column approximate minimum degree permutation. +% P = COLAMD (S) returns the column approximate minimum degree permutation +% vector for the sparse matrix S. For a non-symmetric matrix S, S (:,P) +% tends to have sparser LU factors than S. The Cholesky factorization of +% S (:,P)' * S (:,P) also tends to be sparser than that of S'*S. COLAMD +% tends to be faster than COLMMD and tends to return a better ordering. +% +% See also COLMMD, COLPERM, SPPARMS, SYMAMD, SYMMMD, SYMRCM. +% +% Usage: P = colamd (S) +% P = colamd (S, knobs) +% [P, stats] = colamd (S) +% [P, stats] = colamd (S, knobs) +% +% knobs is an optional two-element input vector. If S is m-by-n, then +% rows with more than (knobs (1))*n entries are ignored. Columns with +% more than (knobs (2))*m entries are removed prior to ordering, and +% ordered last in the output permutation P. If the knobs parameter is not +% present, then 0.5 is used instead, for both knobs (1) and knobs (2). +% knobs (3) controls the printing of statistics and error messages. +% +% stats is an optional 20-element output vector that provides data about the +% ordering and the validity of the input matrix S. Ordering statistics are +% in stats (1:3). stats (1) and stats (2) are the number of dense or empty +% rows and columns ignored by COLAMD and stats (3) is the number of +% garbage collections performed on the internal data structure used by +% COLAMD (roughly of size 2.2*nnz(S) + 4*m + 7*n integers). +% +% MATLAB built-in functions are intended to generate valid sparse matrices, +% with no duplicate entries, with ascending row indices of the nonzeros +% in each column, with a non-negative number of entries in each column (!) +% and so on. If a matrix is invalid, then COLAMD may or may not be able +% to continue. If there are duplicate entries (a row index appears two or +% more times in the same column) or if the row indices in a column are out +% of order, then COLAMD can correct these errors by ignoring the duplicate +% entries and sorting each column of its internal copy of the matrix S (the +% input matrix S is not repaired, however). If a matrix is invalid in other +% ways then COLAMD cannot continue, an error message is printed, and no +% output arguments (P or stats) are returned. COLAMD is thus a simple way +% to check a sparse matrix to see if it's valid. +% +% stats (4:7) provide information if COLAMD was able to continue. The +% matrix is OK if stats (4) is zero, or 1 if invalid. stats (5) is the +% rightmost column index that is unsorted or contains duplicate entries, +% or zero if no such column exists. stats (6) is the last seen duplicate +% or out-of-order row index in the column index given by stats (5), or zero +% if no such row index exists. stats (7) is the number of duplicate or +% out-of-order row indices. +% +% stats (8:20) is always zero in the current version of COLAMD (reserved +% for future use). +% +% The ordering is followed by a column elimination tree post-ordering. +% +% Authors: +% +% The authors of the code itself are Stefan I. Larimore and Timothy A. +% Davis (davis@cise.ufl.edu), University of Florida. The algorithm was +% developed in collaboration with John Gilbert, Xerox PARC, and Esmond +% Ng, Oak Ridge National Laboratory. +% +% Date: +% +% September 8, 2003. Version 2.3. +% +% Acknowledgements: +% +% This work was supported by the National Science Foundation, under +% grants DMS-9504974 and DMS-9803599. + +% Notice: +% +% Copyright (c) 1998-2003 by the University of Florida. +% All Rights Reserved. +% +% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c +% file) for the License. +% +% Availability: +% +% The colamd/symamd library is available at +% +% http://www.cise.ufl.edu/research/sparse/colamd/ +% + +%------------------------------------------------------------------------------- +% Perform the colamd ordering: +%------------------------------------------------------------------------------- + +if (nargout <= 1 & nargin == 1) + p = colamdmex (S) ; +elseif (nargout <= 1 & nargin == 2) + p = colamdmex (S, knobs) ; +elseif (nargout == 2 & nargin == 1) + [p, stats] = colamdmex (S) ; +elseif (nargout == 2 & nargin == 2) + [p, stats] = colamdmex (S, knobs) ; +else + error ('colamd: incorrect number of input and/or output arguments') ; +end + +%------------------------------------------------------------------------------- +% column elimination tree post-ordering: +%------------------------------------------------------------------------------- + +[ignore, q] = sparsfun ('coletree', S (:,p)) ; +p = p (q) ; + diff --git a/liboctave/COLAMD/colamd_demo.m b/liboctave/COLAMD/colamd_demo.m new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd_demo.m @@ -0,0 +1,170 @@ +% Demo for colamd: column approximate minimum degree ordering algorithm. +% +% The following m-files and mexFunctions provide alternative sparse matrix +% ordering methods for MATLAB. They are typically faster (sometimes much +% faster) and typically provide better orderings than their MATLAB counterparts: +% +% colamd a replacement for colmmd. +% +% Typical usage: p = colamd (A) ; +% +% symamd a replacement for symmmd. Based on colamd. +% +% Typical usage: p = symamd (A) ; +% +% For a description of the methods used, see the colamd.c file. +% +% September 8, 2003. Version 2.3. +% http://www.cise.ufl.edu/research/sparse/colamd/ +% + +%------------------------------------------------------------------------------- +% Print the introduction, the help info, and compile the mexFunctions +%------------------------------------------------------------------------------- + +more on + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Colamd/symamd demo.') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +help colamd_demo ; + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Colamd help information:') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +help colamd ; + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Symamd help information:') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +help symamd ; + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'colamd and symamd mexFunctions will now be compiled.') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +s = input ('\n\nHit any key (or type ''n'' to skip compilation): ', 's') ; +if (~strcmp (s, 'n')) + disp ('mex -O colamdmex.c colamd.c') ; mex -O colamdmex.c colamd.c + disp ('mex -O symamdmex.c colamd.c') ; mex -O symamdmex.c colamd.c +end + +%------------------------------------------------------------------------------- +% Solving Ax=b +%------------------------------------------------------------------------------- + +n = 100 ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Solving Ax=b for a small %d-by-%d random matrix:', n, n) ; +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, '\nNOTE: Random sparse matrices are AWFUL test cases.\n') ; +fprintf (1, 'They''re just easy to generate in a demo.\n') ; + +% set up the system + +rand ('state', 0) ; +randn ('state', 0) ; +spparms ('default') ; +A = sprandn (n, n, 5/n) + speye (n) ; +b = (1:n)' ; + +fprintf (1, '\n\nSolving via lu (PAQ = LU), where Q is from colamd:\n') ; +q = colamd (A) ; +I = speye (n) ; +Q = I (:, q) ; +[L,U,P] = lu (A*Q) ; +fl = luflops (L, U) ; +x = Q * (U \ (L \ (P * b))) ; +fprintf (1, '\nFlop count for [L,U,P] = lu (A*Q): %d\n', fl) ; +fprintf (1, 'residual: %e\n', norm (A*x-b)); + +fprintf (1, '\n\nSolving via lu (PAQ = LU), where Q is from colmmd:\n') ; +q = colmmd (A) ; +I = speye (n) ; +Q = I (:, q) ; +[L,U,P] = lu (A*Q) ; +fl = luflops (L, U) ; +x = Q * (U \ (L \ (P * b))) ; +fprintf (1, '\nFlop count for [L,U,P] = lu (A*Q): %d\n', fl) ; +fprintf (1, 'residual: %e\n', norm (A*x-b)); + +fprintf (1, '\n\nSolving via lu (PA = LU), without regard for sparsity:\n') ; +[L,U,P] = lu (A) ; +fl = luflops (L, U) ; +x = U \ (L \ (P * b)) ; +fprintf (1, '\nFlop count for [L,U,P] = lu (A*Q): %d\n', fl) ; +fprintf (1, 'residual: %e\n', norm (A*x-b)); + +%------------------------------------------------------------------------------- +% Large demo for colamd +%------------------------------------------------------------------------------- + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Large demo for colamd (symbolic analysis only):') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; + +rand ('state', 0) ; +randn ('state', 0) ; +spparms ('default') ; +n = 1000 ; +fprintf (1, 'Generating a random %d-by-%d sparse matrix.\n', n, n) ; +A = sprandn (n, n, 5/n) + speye (n) ; + +fprintf (1, '\n\nUnordered matrix:\n') ; +lnz = symbfact (A, 'col') ; +fprintf (1, 'nz in Cholesky factors of A''A: %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A''A: %d\n', sum (lnz.^2)) ; + +tic ; +p = colamd (A) ; +t = toc ; +lnz = symbfact (A (:,p), 'col') ; +fprintf (1, '\n\nColamd run time: %f\n', t) ; +fprintf (1, 'colamd ordering quality: \n') ; +fprintf (1, 'nz in Cholesky factors of A(:,p)''A(:,p): %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A(:,p)''A(:,p): %d\n', sum (lnz.^2)) ; + +tic ; +p = colmmd (A) ; +t = toc ; +lnz = symbfact (A (:,p), 'col') ; +fprintf (1, '\n\nColmmd run time: %f\n', t) ; +fprintf (1, 'colmmd ordering quality: \n') ; +fprintf (1, 'nz in Cholesky factors of A(:,p)''A(:,p): %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A(:,p)''A(:,p): %d\n', sum (lnz.^2)) ; + +%------------------------------------------------------------------------------- +% Large demo for symamd +%------------------------------------------------------------------------------- + +fprintf (1, '\n-----------------------------------------------------------\n') ; +fprintf (1, 'Large demo for symamd (symbolic analysis only):') ; +fprintf (1, '\n-----------------------------------------------------------\n') ; + +fprintf (1, 'Generating a random symmetric %d-by-%d sparse matrix.\n', n, n) ; +A = A+A' ; + +fprintf (1, '\n\nUnordered matrix:\n') ; +lnz = symbfact (A, 'sym') ; +fprintf (1, 'nz in Cholesky factors of A: %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A: %d\n', sum (lnz.^2)) ; + +tic ; +p = symamd (A) ; +t = toc ; +lnz = symbfact (A (p,p), 'sym') ; +fprintf (1, '\n\nSymamd run time: %f\n', t) ; +fprintf (1, 'symamd ordering quality: \n') ; +fprintf (1, 'nz in Cholesky factors of A(p,p): %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A(p,p): %d\n', sum (lnz.^2)) ; + +tic ; +p = symmmd (A) ; +t = toc ; +lnz = symbfact (A (p,p), 'sym') ; +fprintf (1, '\n\nSymmmd run time: %f\n', t) ; +fprintf (1, 'symmmd ordering quality: \n') ; +fprintf (1, 'nz in Cholesky factors of A(p,p): %d\n', sum (lnz)) ; +fprintf (1, 'flop count for Cholesky of A(p,p): %d\n', sum (lnz.^2)) ; + +more off + diff --git a/liboctave/COLAMD/colamd_example.c b/liboctave/COLAMD/colamd_example.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd_example.c @@ -0,0 +1,182 @@ +/* ========================================================================== */ +/* === colamd and symamd example ============================================ */ +/* ========================================================================== */ + +/* + colamd example of use, to order the columns of a 5-by-4 matrix with + 11 nonzero entries in the following nonzero pattern, with default knobs. + + x 0 x 0 + x 0 x x + 0 x x 0 + 0 0 x x + x x 0 0 + + symamd example of use, to order the rows and columns of a 5-by-5 + matrix with 13 nonzero entries in the following nonzero pattern, + with default knobs. + + x x 0 0 0 + x x x x 0 + 0 x x 0 0 + 0 x 0 x x + 0 0 0 x x + + (where x denotes a nonzero value). + + September 8, 2003. Version 2.3. + + See http://www.cise.ufl.edu/research/sparse/colamd/ (the colamd.c file) + for the routines this program calls, and for the License. +*/ + +/* ========================================================================== */ + +#include +#include "colamd.h" + +#define A_NNZ 11 +#define A_NROW 5 +#define A_NCOL 4 +#define ALEN (COLAMD_RECOMMENDED (A_NNZ, A_NCOL, A_NROW)) + +#define B_NNZ 4 +#define B_N 5 + +int main (int argc, char **argv) +{ + + /* ====================================================================== */ + /* input matrix A definition */ + /* ====================================================================== */ + + int A [ALEN] = { + + 0, 1, 4, /* row indices of nonzeros in column 0 */ + 2, 4, /* row indices of nonzeros in column 1 */ + 0, 1, 2, 3, /* row indices of nonzeros in column 2 */ + 1, 3} ; /* row indices of nonzeros in column 3 */ + + int p [ ] = { + + 0, /* column 0 is in A [0..2] */ + 3, /* column 1 is in A [3..4] */ + 5, /* column 2 is in A [5..8] */ + 9, /* column 3 is in A [9..10] */ + A_NNZ} ; /* number of nonzeros in A */ + + /* ====================================================================== */ + /* input matrix B definition */ + /* ====================================================================== */ + + int B [ ] = { /* Note: only strictly lower triangular part */ + /* is included, since symamd ignores the */ + /* diagonal and upper triangular part of B. */ + + 1, /* row indices of nonzeros in column 0 */ + 2, 3, /* row indices of nonzeros in column 1 */ + /* row indices of nonzeros in column 2 (none) */ + 4 /* row indices of nonzeros in column 3 */ + } ; /* row indices of nonzeros in column 4 (none) */ + + int q [ ] = { + + 0, /* column 0 is in B [0] */ + 1, /* column 1 is in B [1..2] */ + 3, /* column 2 is empty */ + 3, /* column 3 is in B [3] */ + 4, /* column 4 is empty */ + B_NNZ} ; /* number of nonzeros in strictly lower B */ + + /* ====================================================================== */ + /* other variable definitions */ + /* ====================================================================== */ + + int perm [B_N+1] ; /* note the size is N+1 */ + int stats [COLAMD_STATS] ; /* for colamd and symamd output statistics */ + + int row, col, pp, length, ok ; + + /* ====================================================================== */ + /* dump the input matrix A */ + /* ====================================================================== */ + + printf ("colamd %d-by-%d input matrix:\n", A_NROW, A_NCOL) ; + for (col = 0 ; col < A_NCOL ; col++) + { + length = p [col+1] - p [col] ; + printf ("Column %d, with %d entries:\n", col, length) ; + for (pp = p [col] ; pp < p [col+1] ; pp++) + { + row = A [pp] ; + printf (" row %d\n", row) ; + } + } + + /* ====================================================================== */ + /* order the matrix. Note that this destroys A and overwrites p */ + /* ====================================================================== */ + + ok = colamd (A_NROW, A_NCOL, ALEN, A, p, (double *) NULL, stats) ; + colamd_report (stats) ; + + if (!ok) + { + printf ("colamd error!\n") ; + exit (1) ; + } + + /* ====================================================================== */ + /* print the column ordering */ + /* ====================================================================== */ + + printf ("colamd column ordering:\n") ; + printf ("1st column: %d\n", p [0]) ; + printf ("2nd column: %d\n", p [1]) ; + printf ("3rd column: %d\n", p [2]) ; + printf ("4th column: %d\n", p [3]) ; + + /* ====================================================================== */ + /* dump the strictly lower triangular part of symmetric input matrix B */ + /* ====================================================================== */ + + printf ("\n\nsymamd %d-by-%d input matrix:\n", B_N, B_N) ; + printf ("Entries in strictly lower triangular part:\n") ; + for (col = 0 ; col < B_N ; col++) + { + length = q [col+1] - q [col] ; + printf ("Column %d, with %d entries:\n", col, length) ; + for (pp = q [col] ; pp < q [col+1] ; pp++) + { + row = B [pp] ; + printf (" row %d\n", row) ; + } + } + + /* ====================================================================== */ + /* order the matrix B. Note that this does not modify B or q. */ + /* ====================================================================== */ + + ok = symamd (B_N, B, q, perm, (double *) NULL, stats, &calloc, &free) ; + symamd_report (stats) ; + + if (!ok) + { + printf ("symamd error!\n") ; + exit (1) ; + } + + /* ====================================================================== */ + /* print the symmetric ordering */ + /* ====================================================================== */ + + printf ("symamd column ordering:\n") ; + printf ("1st row/column: %d\n", perm [0]) ; + printf ("2nd row/column: %d\n", perm [1]) ; + printf ("3rd row/column: %d\n", perm [2]) ; + printf ("4th row/column: %d\n", perm [3]) ; + printf ("5th row/column: %d\n", perm [4]) ; + + exit (0) ; +} + diff --git a/liboctave/COLAMD/colamd_example.out b/liboctave/COLAMD/colamd_example.out new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd_example.out @@ -0,0 +1,48 @@ +colamd 5-by-4 input matrix: +Column 0, with 3 entries: + row 0 + row 1 + row 4 +Column 1, with 2 entries: + row 2 + row 4 +Column 2, with 4 entries: + row 0 + row 1 + row 2 + row 3 +Column 3, with 2 entries: + row 1 + row 3 +colamd: OK. +colamd: number of dense or empty rows ignored: 1 +colamd: number of dense or empty columns ignored: 2 +colamd: number of garbage collections performed: 0 +colamd column ordering: +1st column: 1 +2nd column: 3 +3rd column: 0 +4th column: 2 + + +symamd 5-by-5 input matrix: +Entries in strictly lower triangular part: +Column 0, with 1 entries: + row 1 +Column 1, with 2 entries: + row 2 + row 3 +Column 2, with 0 entries: +Column 3, with 1 entries: + row 4 +Column 4, with 0 entries: +symamd: OK. +symamd: number of dense or empty rows ignored: 0 +symamd: number of dense or empty columns ignored: 0 +symamd: number of garbage collections performed: 0 +symamd column ordering: +1st row/column: 0 +2nd row/column: 2 +3rd row/column: 1 +4th row/column: 3 +5th row/column: 4 diff --git a/liboctave/COLAMD/colamd_test.m b/liboctave/COLAMD/colamd_test.m new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamd_test.m @@ -0,0 +1,521 @@ +function colamd_test (spumoni) +% +% colamd_test (spumoni) +% +% COLAMD and SYMAMD testing function. Here we try to give colamd and symamd +% every possible type of matrix and erroneous input that they may encounter. +% We want either a valid permutation returned or we want them to fail +% gracefully. If the optional spumoni argument is present, additional +% diagnostic messages are printed during the test: +% +% spumoni: +% 0: very little, just a progress meter (default) +% 1: lots +% 2: far too much +% +% You are prompted as to whether or not the colamd and symand routines and +% the test mexFunctions are to be compiled. +% +% Tim Davis +% September 8, 2003. Version 2.3. +% http://www.cise.ufl.edu/research/sparse/colamd/ + +help colamd_test + +s = input (... +'Compile colamd, symand, and the test codes? (y/n, default is yes): ', 's') ; + +do_compile = 1 ; +if (~isempty (s)) + if (s (1) == 'n' | s (1) == 'N') + do_compile = 0 ; + end +end + +if (do_compile) + fprintf ('Compiling colamd, symamd, and test mexFunctions.\n') ; + fprintf ('mex -O colamdmex.c colamd.c\n') ; + mex -O colamdmex.c colamd.c + fprintf ('mex -O symamdmex.c colamd.c\n') ; + mex -O symamdmex.c colamd.c + fprintf ('mex -O colamdtestmex.c colamd.c\n') ; + mex -O colamdtestmex.c colamd.c + fprintf ('mex -O symamdtestmex.c colamd.c\n') ; + mex -O symamdtestmex.c colamd.c + fprintf ('Done compiling.\n') ; +end + +fprintf ('\nThe following codes will be tested:\n') ; +which colamd +which symamd +which colamdmex +which symamdmex + +fprintf ('\nStarting the tests. Please be patient.\n') ; + +rand ('state', 0) ; +randn ('state', 0) ; +if (nargin < 1) + spumoni = 0 ; +end +old = spparms ('spumoni') ; +spparms ('spumoni', spumoni) ; + + +fprintf ('Null matrices') ; +A = zeros (0,0) ; +A = sparse (A) ; + +[p, stats] = colamd (A, [.5 .5 spumoni]) ; +check_perm (p, A) ; + +[p, stats] = symamd (A, [.5 spumoni]) ; +check_perm (p, A) ; + +A = zeros (0, 100) ; +A = sparse (A) ; +[p, stats] = colamd (A, [.5 .5 spumoni]) ; +check_perm (p, A) ; + +A = zeros (100, 0) ; +A = sparse (A) ; +[p, stats] = colamd (A, [.5 .5 spumoni]) ; +check_perm (p, A) ; +fprintf (' OK\n') ; + + +fprintf ('Matrices with a few dense row/cols\n') ; + +for trial = 1:20 + + % random square unsymmetric matrix + A = rand_matrix (1000, 1000, 1, 10, 20) ; + [m n] = size (A) ; + + + for tol = [0 0.001 0.005 0.01:0.01:0.10 0.5:.1:1] + + [p, stats] = colamd (A, [tol tol spumoni]) ; + check_perm (p, A) ; + + B = A + A' ; + [p, stats] = symamd (B, [tol spumoni]) ; + check_perm (p, A) ; + + [p, stats] = colamd (A, [tol 1 spumoni]) ; + check_perm (p, A) ; + + [p, stats] = colamd (A, [1 tol spumoni]) ; + check_perm (p, A) ; + + fprintf ('.') ; + + end +end +fprintf (' OK\n') ; + +fprintf ('General matrices\n') ; +for trial = 1:400 + + % matrix of random mtype + mtype = irand (3) ; + A = rand_matrix (2000, 2000, mtype, 0, 0) ; + [m n] = size (A) ; + p = colamd (A) ; + check_perm (p, A) ; + if (mtype == 3) + p = symamd (A) ; + check_perm (p, A) ; + end + + fprintf ('.') ; +end +fprintf (' OK\n') ; + +fprintf ('Test error handling with invalid inputs\n') ; + +% Check different erroneous input. +for trial = 1:30 + + A = rand_matrix (1000, 1000, 2, 0, 0) ; + [m n] = size (A) ; + + for err = 1:13 + + p = Tcolamd (A, [1 1 spumoni 0 err]) ; + if p ~= -1 + check_perm (p, A) ; + end + + if (err == 1) + % check different (valid) input args to colamd + p = Acolamd (A, spumoni) ; + + p2 = Acolamd (A, spumoni, [.5 .5 spumoni 0 0]) ; + if (any (p ~= p2)) + error ('colamd: mismatch 1!') ; + end + [p2 stats] = Acolamd (A, spumoni) ; + if (any (p ~= p2)) + error ('colamd: mismatch 2!') ; + end + [p2 stats] = Acolamd (A, spumoni, [.5 .5 spumoni 0 0]) ; + if (any (p ~= p2)) + error ('colamd: mismatch 3!') ; + end + end + + B = A'*A ; + p = Tsymamd (B, [1 spumoni err]) ; + if p ~= -1 + check_perm (p, A) ; + end + + if (err == 1) + + % check different (valid) input args to symamd + p = Asymamd (B, spumoni) ; + check_perm (p, A) ; + p2 = Asymamd (B, spumoni, [.5 spumoni 0]) ; + if (any (p ~= p2)) + error ('symamd: mismatch 1!') ; + end + [p2 stats] = Asymamd (B, spumoni) ; + if (any (p ~= p2)) + error ('symamd: mismatch 2!') ; + end + [p2 stats] = Asymamd (B, spumoni, [.5 spumoni 0]) ; + if (any (p ~= p2)) + error ('symamd: mismatch 3!') ; + end + end + + fprintf ('.') ; + end + +end +fprintf (' OK\n') ; + +fprintf ('Matrices with a few empty columns\n') ; + +for trial = 1:400 + + % some are square, some are rectangular + n = 0 ; + while (n < 5) + A = rand_matrix (1000, 1000, irand (2), 0, 0) ; + [m n] = size (A) ; + end + + % Add 5 null columns at random locations. + null_col = randperm (n) ; + null_col = sort (null_col (1:5)) ; + A (:, null_col) = 0 ; + + % Order the matrix and make sure that the null columns are ordered last. + [p, stats] = colamd (A, [1 1 spumoni]) ; + check_perm (p, A) ; + + if (stats (2) ~= 5) + error ('colamd: wrong number of null columns') ; + end + if (any (null_col ~= p ((n-4):n))) + error ('colamd: Null cols are not ordered last in natural order') ; + end + + fprintf ('.') ; + +end +fprintf (' OK\n') ; + +fprintf ('Matrices with a few empty rows and columns\n') ; + +for trial = 1:400 + + % symmetric matrices + n = 0 ; + while (n < 5) + A = rand_matrix (1000, 1000, 3, 0, 0) ; + [m n] = size (A) ; + end + + % Add 5 null columns and rows at random locations. + null_col = randperm (n) ; + null_col = sort (null_col (1:5)) ; + A (:, null_col) = 0 ; + A (null_col, :) = 0 ; + + % Order the matrix and make sure that the null rows/cols are ordered last. + [p,stats] = symamd (A, [1 spumoni]) ; + check_perm (p, A) ; + + % find actual number of null rows and columns + Alo = tril (A, -1) ; + nnull = length (find (sum (Alo') == 0 & sum (Alo) == 0)) ; + + if (stats (2) ~= nnull | nnull < 5) + error ('symamd: wrong number of null columns') ; + end + if (any (null_col ~= p ((n-4):n))) + error ('symamd: Null cols are not ordered last in natural order') ; + end + + fprintf ('.') ; + +end +fprintf (' OK\n') ; + +fprintf ('Matrices with a few empty rows\n') ; + +% Test matrices with null rows inserted. + +for trial = 1:400 + + m = 0 ; + while (m < 5) + A = rand_matrix (1000, 1000, 2, 0, 0) ; + [m n] = size (A) ; + end + + % Add 5 null rows at random locations. + null_row = randperm (m) ; + null_row = sort (null_row (1:5)) ; + A (null_row, :) = 0 ; + + p = colamd (A, [.5 .5 spumoni]) ; + check_perm (p, A) ; + if (stats (1) ~= 5) + error ('colamd: wrong number of null rows') ; + end + fprintf ('.') ; +end +fprintf (' OK\n') ; + + +fprintf ('\ncolamd and symamd: all tests passed\n\n') ; +spparms ('spumoni', old) ; + +%------------------------------------------------------------------------------- +% Acolamd: compare colamd and Tcolamd results +%------------------------------------------------------------------------------- + +function [p,stats] = Acolamd (S, spumoni, knobs) + +if (nargin < 2) + spumoni = 0 ; +end + +if (nargin < 3) + if (nargout == 1) + [p] = colamd (S) ; + [p1] = Tcolamd (S, [.5 .5 spumoni 0 0]) ; + else + [p, stats] = colamd (S) ; + [p1, stats1] = Tcolamd (S, [.5 .5 spumoni 0 0]) ; + end +else + if (nargout == 1) + [p] = colamd (S, knobs (1:3)) ; + [p1] = Tcolamd (S, knobs) ; + else + [p, stats] = colamd (S, knobs (1:3)) ; + [p1, stats1] = Tcolamd (S, knobs) ; + end +end + +check_perm (p, S) ; +check_perm (p1, S) ; + +if (any (p1 ~= p)) + error ('Acolamd mismatch!') ; +end + + +%------------------------------------------------------------------------------- +% Asymamd: compare symamd and Tsymamd results +%------------------------------------------------------------------------------- + +function [p,stats] = Asymamd (S, spumoni, knobs) + +if (nargin < 2) + spumoni = 0 ; +end + +if (nargin < 3) + if (nargout == 1) + [p] = symamd (S) ; + [p1] = Tsymamd (S, [.5 spumoni 0]) ; + else + [p, stats] = symamd (S) ; + [p1, stats1] = Tsymamd (S, [.5 spumoni 0]) ; + end +else + if (nargout == 1) + [p] = symamd (S, knobs (1:2)) ; + [p1] = Tsymamd (S, knobs) ; + else + [p, stats] = symamd (S, knobs (1:2)) ; + [p1, stats1] = Tsymamd (S, knobs) ; + end +end + +if (any (p1 ~= p)) + error ('Asymamd mismatch!') ; +end + + +%------------------------------------------------------------------------------- +% check_perm: check for a valid permutation vector +%------------------------------------------------------------------------------- + +function check_perm (p, A) + +if (isempty (A) & isempty (p)) + % empty permutation vectors of empty matrices are OK + return +end + +if (isempty (p)) + error ('bad permutation: cannot be empty') ; +end + +[m n] = size (A) ; +[pm pn] = size (p) ; +if (pn == 1) + % force p to be a row vector + p = p' ; + [pm pn] = size (p) ; +end + +if (n ~= pn) + error ('bad permutation: wrong size') ; +end + +if (pm ~= 1) ; + % p must be a vector + error ('bad permutation: not a vector') ; +else + if (any (sort (p) - (1:pn))) + error ('bad permutation') ; + end +end + +%------------------------------------------------------------------------------- +% irand: return a random integer between 1 and n +%------------------------------------------------------------------------------- + +function i = irand (n) +i = min (n, 1 + floor (rand * n)) ; + +%------------------------------------------------------------------------------- +% rand_matrix: return a random sparse matrix +%------------------------------------------------------------------------------- + +function A = rand_matrix (nmax, mmax, mtype, drows, dcols) +% +% A = rand_matrix (nmax, mmax, mtype, drows, dcols) +% +% A binary matrix of random size, at most nmax-by-mmax, with drows dense rows +% and dcols dense columns. +% +% mtype 1: square unsymmetric (mmax is ignored) +% mtype 2: rectangular +% mtype 3: symmetric (mmax is ignored) + +n = irand (nmax) ; +if (mtype ~= 2) + % square + m = n ; +else + m = irand (mmax) ; +end + +A = sprand (m, n, 10 / max (m,n)) ; + +if (drows > 0) + % add dense rows + for k = 1:drows + i = irand (m) ; + nz = irand (n) ; + p = randperm (n) ; + p = p (1:nz) ; + A (i,p) = 1 ; + end +end + +if (dcols > 0) + % add dense cols + for k = 1:dcols + j = irand (n) ; + nz = irand (m) ; + p = randperm (m) ; + p = p (1:nz) ; + A (p,j) = 1 ; + end +end + +A = spones (A) ; + +% ensure that there are no empty columns +d = find (full (sum (A)) == 0) ; +A (m,d) = 1 ; + +% ensure that there are no empty rows +d = find (full (sum (A,2)) == 0) ; +A (d,n) = 1 ; + +if (mtype == 3) + % symmetric + A = A + A' + speye (n) ; +end + +A = spones (A) ; + +%------------------------------------------------------------------------------- +% Tcolamd: run colamd in a testing mode +%------------------------------------------------------------------------------- + +function [p,stats] = Tcolamd (S, knobs) + +if (nargout <= 1 & nargin == 1) + p = colamdtestmex (S) ; +elseif (nargout <= 1 & nargin == 2) + p = colamdtestmex (S, knobs) ; +elseif (nargout == 2 & nargin == 1) + [p, stats] = colamdtestmex (S) ; +elseif (nargout == 2 & nargin == 2) + [p, stats] = colamdtestmex (S, knobs) ; +else + error ('colamd: incorrect number of input and/or output arguments') ; +end + +if (p (1) ~= -1) + [ignore, q] = sparsfun ('coletree', S (:,p)) ; + p = p (q) ; + check_perm (p, S) ; +end + +%------------------------------------------------------------------------------- +% Tsymamd: run symamd in a testing mode +%------------------------------------------------------------------------------- + +function [p, stats] = Tsymamd (S, knobs) + +if (nargout <= 1 & nargin == 1) + p = symamdtestmex (S) ; +elseif (nargout <= 1 & nargin == 2) + p = symamdtestmex (S, knobs) ; +elseif (nargout == 2 & nargin == 1) + [p, stats] = symamdtestmex (S) ; +elseif (nargout == 2 & nargin == 2) + [p, stats] = symamdtestmex (S, knobs) ; +else + error ('symamd: incorrect number of input and/or output arguments') ; +end + +if (p (1) ~= -1) + [ignore, q] = sparsfun ('symetree', S (p,p)) ; + p = p (q) ; + check_perm (p, S) ; +end + diff --git a/liboctave/COLAMD/colamdmex.c b/liboctave/COLAMD/colamdmex.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamdmex.c @@ -0,0 +1,250 @@ +/* ========================================================================== */ +/* === colamd mexFunction =================================================== */ +/* ========================================================================== */ + +/* + Usage: + + P = colamd (A) ; + + P = colamd (A, knobs) ; + + [ P, stats ] = colamd (A) ; + + [ P, stats ] = colamd (A, knobs) ; + + Returns a permutation vector P such that the LU factorization of A (:,P) + tends to be sparser than that of A. The Cholesky factorization of + (A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A. + This routine provides the same functionality as COLMMD, but is much faster + and returns a better permutation vector. Note that the COLMMD m-file in + MATLAB 5.2 also performs a column elimination tree post-ordering. This + mexFunction does not do this post-ordering. This mexFunction is a + replacement for the p = sparsfun ('colmmd', A) operation. + + The knobs and stats vectors are optional: + + knobs (1) rows with more than (knobs (1))*n_col entries + are removed prior to ordering. If knobs is not present, + then the default is used (0.5). + + knobs (2) columns with more than (knobs (2))*n_row entries + are removed prior to ordering, and placed last in the + column permutation. If knobs is not present, + then the default is used (0.5). + + knobs (3) print level, similar to spparms ('spumoni') + + stats (1) the number of dense (or empty) rows ignored + + stats (2) the number of dense (or empty) columms. These + are ordered last, in their natural order. + + stats (3) the number of garbage collections performed. + + stats (4) return status: + + 0: matrix is a valid MATLAB matrix. + + 1: matrix has duplicate entries or unsorted columns. + This should not occur in a valid MATLAB matrix, + but the ordering proceeded anyway by sorting the + row indices in each column and by ignoring the + duplicate row indices in each column. See + stats (5:7) for more information. + + stats (5) highest numbered column that is unsorted or has + duplicate entries (zero if none) + + stats (6) last seen duplicate or unsorted row index + (zero if none) + + stats (7) number of duplicate or unsorted row indices + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Notice: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c + file) for the License. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/colamdmex.c + file. It requires the colamd.c and colamd.h files. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" +#include "mex.h" +#include "matrix.h" +#include +#include + +/* ========================================================================== */ +/* === colamd mexFunction =================================================== */ +/* ========================================================================== */ + +void mexFunction +( + /* === Parameters ======================================================= */ + + int nlhs, /* number of left-hand sides */ + mxArray *plhs [], /* left-hand side matrices */ + int nrhs, /* number of right--hand sides */ + const mxArray *prhs [] /* right-hand side matrices */ +) +{ + /* === Local variables ================================================== */ + + int *A ; /* colamd's copy of the matrix, and workspace */ + int *p ; /* colamd's copy of the column pointers */ + int Alen ; /* size of A */ + int n_col ; /* number of columns of A */ + int n_row ; /* number of rows of A */ + int nnz ; /* number of entries in A */ + int full ; /* TRUE if input matrix full, FALSE if sparse */ + double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */ + double *out_perm ; /* output permutation vector */ + double *out_stats ; /* output stats vector */ + double *in_knobs ; /* input knobs vector */ + int i ; /* loop counter */ + mxArray *Ainput ; /* input matrix handle */ + int spumoni ; /* verbosity variable */ + int stats [COLAMD_STATS] ; /* stats for colamd */ + + /* === Check inputs ===================================================== */ + + if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) + { + mexErrMsgTxt ( + "colamd: incorrect number of input and/or output arguments") ; + } + + /* === Get knobs ======================================================== */ + + colamd_set_defaults (knobs) ; + spumoni = 0 ; + + /* check for user-passed knobs */ + if (nrhs == 2) + { + in_knobs = mxGetPr (prhs [1]) ; + i = mxGetNumberOfElements (prhs [1]) ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; + if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [COLAMD_DENSE_COL] ; + if (i > 2) spumoni = (int) in_knobs [2] ; + } + + /* print knob settings if spumoni is set */ + if (spumoni > 0) + { + mexPrintf ("colamd: dense row fraction: %f\n", + knobs [COLAMD_DENSE_ROW]) ; + mexPrintf ("colamd: dense col fraction: %f\n", + knobs [COLAMD_DENSE_COL]) ; + } + + /* === If A is full, convert to a sparse matrix ========================= */ + + Ainput = (mxArray *) prhs [0] ; + if (mxGetNumberOfDimensions (Ainput) != 2) + { + mexErrMsgTxt ("colamd: input matrix must be 2-dimensional") ; + } + full = !mxIsSparse (Ainput) ; + if (full) + { + mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ; + } + + /* === Allocate workspace for colamd ==================================== */ + + /* get size of matrix */ + n_row = mxGetM (Ainput) ; + n_col = mxGetN (Ainput) ; + + /* get column pointer vector so we can find nnz */ + p = (int *) mxCalloc (n_col+1, sizeof (int)) ; + (void) memcpy (p, mxGetJc (Ainput), (n_col+1)*sizeof (int)) ; + nnz = p [n_col] ; + Alen = colamd_recommended (nnz, n_row, n_col) ; + + /* === Copy input matrix into workspace ================================= */ + + A = (int *) mxCalloc (Alen, sizeof (int)) ; + (void) memcpy (A, mxGetIr (Ainput), nnz*sizeof (int)) ; + + if (full) + { + mxDestroyArray (Ainput) ; + } + + /* === Order the columns (destroys A) =================================== */ + + if (!colamd (n_row, n_col, Alen, A, p, knobs, stats)) + { + colamd_report (stats) ; + mexErrMsgTxt ("colamd error!") ; + } + mxFree (A) ; + + /* === Return the permutation vector ==================================== */ + + plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + for (i = 0 ; i < n_col ; i++) + { + /* colamd is 0-based, but MATLAB expects this to be 1-based */ + out_perm [i] = p [i] + 1 ; + } + mxFree (p) ; + + /* === Return the stats vector ========================================== */ + + /* print stats if spumoni > 0 */ + if (spumoni > 0) + { + colamd_report (stats) ; + } + + if (nlhs == 2) + { + plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ; + out_stats = mxGetPr (plhs [1]) ; + for (i = 0 ; i < COLAMD_STATS ; i++) + { + out_stats [i] = stats [i] ; + } + + /* fix stats (5) and (6), for 1-based information on jumbled matrix. */ + /* note that this correction doesn't occur if symamd returns FALSE */ + out_stats [COLAMD_INFO1] ++ ; + out_stats [COLAMD_INFO2] ++ ; + } +} diff --git a/liboctave/COLAMD/colamdtestmex.c b/liboctave/COLAMD/colamdtestmex.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/colamdtestmex.c @@ -0,0 +1,594 @@ +/* ========================================================================== */ +/* === colamdtest mexFunction =============================================== */ +/* ========================================================================== */ + +/* + This MATLAB mexFunction is for testing only. It is not meant for + production use. See colamdmex.c instead. + + Usage: + + [ P, stats ] = colamdtest (A, knobs) ; + + Returns a permutation vector P such that the LU factorization of A (:,P) + tends to be sparser than that of A. The Cholesky factorization of + (A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A. + This routine provides the same functionality as COLMMD, but is much faster + and returns a better permutation vector. Note that the COLMMD m-file in + MATLAB 5.2 also performs a column elimination tree post-ordering. This + mexFunction does not do this post-ordering. This mexFunction is a + replacement for the p = sparsfun ('colmmd', A) operation. + + The knobs and stats vectors are optional: + + knobs (1) rows with more than (knobs (1))*n_col entries + are removed prior to ordering. If knobs is not present, + then the default is used (0.5). + + knobs (2) columns with more than (knobs (2))*n_row entries + are removed prior to ordering, and placed last in the + column permutation. If knobs is not present, + then the default is used (0.5). + + knobs (3) print level, similar to spparms ('spumoni') + + knobs (4) for testing only. Controls the workspace used by + colamd. + + knobs (5) for testing only. Controls how the input matrix is + jumbled prior to calling colamd, to test its error + handling capability. + + stats (1) the number of dense (or empty) rows ignored + + stats (2) the number of dense (or empty) columms. These + are ordered last, in their natural order. + + stats (3) the number of garbage collections performed. + + stats (4) return status: + + 0: matrix is a valid MATLAB matrix. + + 1: matrix has duplicate entries or unsorted columns. + This should not occur in a valid MATLAB matrix, + but the ordering proceeded anyway by sorting the + row indices in each column and by ignoring the + duplicate row indices in each column. See + stats (5:7) for more information. + + stats (5) highest numbered column that is unsorted or has + duplicate entries (zero if none) + + stats (6) last seen duplicate or unsorted row index + (zero if none) + + stats (7) number of duplicate or unsorted row indices + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Notice: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c + file) for the License. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the + http://www.cise.ufl.edu/research/sparse/colamd/colamdtestmex.c + file. It requires the colamd.c and colamd.h files. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" +#include "mex.h" +#include "matrix.h" +#include +#include + +static void dump_matrix +( + int A [ ], + int p [ ], + int n_row, + int n_col, + int Alen, + int limit +) ; + +/* ========================================================================== */ +/* === colamd mexFunction =================================================== */ +/* ========================================================================== */ + +void mexFunction +( + /* === Parameters ======================================================= */ + + int nlhs, /* number of left-hand sides */ + mxArray *plhs [], /* left-hand side matrices */ + int nrhs, /* number of right--hand sides */ + const mxArray *prhs [] /* right-hand side matrices */ +) +{ + /* === Local variables ================================================== */ + + int *A ; /* colamd's copy of the matrix, and workspace */ + int *p ; /* colamd's copy of the column pointers */ + int Alen ; /* size of A */ + int n_col ; /* number of columns of A */ + int n_row ; /* number of rows of A */ + int nnz ; /* number of entries in A */ + int full ; /* TRUE if input matrix full, FALSE if sparse */ + double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */ + double *out_perm ; /* output permutation vector */ + double *out_stats ; /* output stats vector */ + double *in_knobs ; /* input knobs vector */ + int i ; /* loop counter */ + mxArray *Ainput ; /* input matrix handle */ + int spumoni ; /* verbosity variable */ + int stats2 [COLAMD_STATS] ; /* stats for colamd */ + + int *cp, *cp_end, result, col, length ; + int *stats ; + stats = stats2 ; + + /* === Check inputs ===================================================== */ + + if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) + { + mexErrMsgTxt ( + "colamd: incorrect number of input and/or output arguments") ; + } + + if (nrhs != 2) + { + mexErrMsgTxt ("colamdtest: knobs are required") ; + } + /* for testing we require all 5 knobs */ + if (mxGetNumberOfElements (prhs [1]) < 5) + { + mexErrMsgTxt ("colamd: must have all 5 knobs for testing") ; + } + + /* === Get knobs ======================================================== */ + + colamd_set_defaults (knobs) ; + spumoni = 0 ; + + /* check for user-passed knobs */ + if (nrhs == 2) + { + in_knobs = mxGetPr (prhs [1]) ; + i = mxGetNumberOfElements (prhs [1]) ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; + if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [COLAMD_DENSE_COL] ; + if (i > 2) spumoni = (int) in_knobs [2] ; + } + + /* print knob settings if spumoni is set */ + if (spumoni > 0) + { + mexPrintf ("colamd: dense row fraction: %f\n", + knobs [COLAMD_DENSE_ROW]) ; + mexPrintf ("colamd: dense col fraction: %f\n", + knobs [COLAMD_DENSE_COL]) ; + } + + /* === If A is full, convert to a sparse matrix ========================= */ + + Ainput = (mxArray *) prhs [0] ; + if (mxGetNumberOfDimensions (Ainput) != 2) + { + mexErrMsgTxt ("colamd: input matrix must be 2-dimensional") ; + } + full = !mxIsSparse (Ainput) ; + if (full) + { + mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ; + } + + /* === Allocate workspace for colamd ==================================== */ + + /* get size of matrix */ + n_row = mxGetM (Ainput) ; + n_col = mxGetN (Ainput) ; + + /* get column pointer vector so we can find nnz */ + p = (int *) mxCalloc (n_col+1, sizeof (int)) ; + (void) memcpy (p, mxGetJc (Ainput), (n_col+1)*sizeof (int)) ; + nnz = p [n_col] ; + Alen = colamd_recommended (nnz, n_row, n_col) ; + + +/* === Modify size of Alen if testing ======================================= */ + +/* + knobs [3] amount of workspace given to colamd. + < 0 : TIGHT memory + > 0 : MIN + knob [3] - 1 + == 0 : RECOMMENDED memory +*/ + +/* Here only for testing */ +#ifdef MIN +#undef MIN +#endif +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define COLAMD_MIN_MEMORY(nnz,n_row,n_col) \ + (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row)) + + /* get knob [3], if negative */ + if (in_knobs [3] < 0) + { + Alen = COLAMD_MIN_MEMORY (nnz, n_row, n_col) + n_col ; + } + else if (in_knobs [3] > 0) + { + Alen = COLAMD_MIN_MEMORY (nnz, n_row, n_col) + in_knobs [3] - 1 ; + } + + /* otherwise, we use the recommended amount set above */ + + /* === Copy input matrix into workspace ================================= */ + + A = (int *) mxCalloc (Alen, sizeof (int)) ; + (void) memcpy (A, mxGetIr (Ainput), nnz*sizeof (int)) ; + + if (full) + { + mxDestroyArray (Ainput) ; + } + + +/* === Jumble matrix ======================================================== */ + +/* + knobs [4] FOR TESTING ONLY: Specifies how to jumble matrix + 0 : No jumbling + 1 : Make n_row less than zero + 2 : Make first pointer non-zero + 3 : Make column pointers not non-decreasing + 4 : Make a column pointer greater or equal to Alen + 5 : Make row indices not strictly increasing + 6 : Make a row index greater or equal to n_row + 7 : Set A = NULL + 8 : Set p = NULL + 9 : Repeat row index + 10: make row indices not sorted + 11: jumble columns massively (note this changes + the pattern of the matrix A.) + 12: Set stats = NULL + 13: Make n_col less than zero +*/ + + /* jumble appropriately */ + switch ((int) in_knobs [4]) + { + + case 0 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: no errors expected\n") ; + } + result = 1 ; /* no errors */ + break ; + + case 1 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: nrow out of range\n") ; + } + result = 0 ; /* nrow out of range */ + n_row = -1 ; + break ; + + case 2 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: p [0] nonzero\n") ; + } + result = 0 ; /* p [0] must be zero */ + p [0] = 1 ; + break ; + + case 3 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: negative length last column\n") ; + } + result = (n_col == 0) ; /* p must be monotonically inc. */ + p [n_col] = p [0] ; + break ; + + case 4 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: Alen too small\n") ; + } + result = 0 ; /* out of memory */ + p [n_col] = Alen ; + break ; + + case 5 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: row index out of range (-1)\n") ; + } + if (nnz > 0) /* row index out of range */ + { + result = 0 ; + A [nnz-1] = -1 ; + } + else + { + if (spumoni > 0) + { + mexPrintf ("Note: no row indices to put out of range\n") ; + } + result = 1 ; + } + break ; + + case 6 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: row index out of range (n_row)\n") ; + } + if (nnz > 0) /* row index out of range */ + { + if (spumoni > 0) + { + mexPrintf ("Changing A[nnz-1] from %d to %d\n", + A [nnz-1], n_row) ; + } + result = 0 ; + A [nnz-1] = n_row ; + } + else + { + if (spumoni > 0) + { + mexPrintf ("Note: no row indices to put out of range\n") ; + } + result = 1 ; + } + break ; + + case 7 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: A not present\n") ; + } + result = 0 ; /* A not present */ + A = (int *) NULL ; + break ; + + case 8 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: p not present\n") ; + } + result = 0 ; /* p not present */ + p = (int *) NULL ; + break ; + + case 9 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: duplicate row index\n") ; + } + result = 1 ; /* duplicate row index */ + + for (col = 0 ; col < n_col ; col++) + { + length = p [col+1] - p [col] ; + if (length > 1) + { + A [p [col]] = A [p [col] + 1] ; + if (spumoni > 0) + { + mexPrintf ("Made duplicate row %d in col %d\n", + A [p [col] + 1], col) ; + } + break ; + } + } + + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, Alen, col+2) ; + } + break ; + + case 10 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: unsorted column\n") ; + } + result = 1 ; /* jumbled columns */ + + for (col = 0 ; col < n_col ; col++) + { + length = p [col+1] - p [col] ; + if (length > 1) + { + i = A[p [col]] ; + A [p [col]] = A[p [col] + 1] ; + A [p [col] + 1] = i ; + if (spumoni > 0) + { + mexPrintf ("Unsorted column %d \n", col) ; + } + break ; + } + } + + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, Alen, col+2) ; + } + break ; + + case 11 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: massive jumbling\n") ; + } + result = 1 ; /* massive jumbling, but no errors */ + srand (1) ; + for (i = 0 ; i < n_col ; i++) + { + cp = &A [p [i]] ; + cp_end = &A [p [i+1]] ; + while (cp < cp_end) + { + *cp++ = rand() % n_row ; + } + } + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, Alen, n_col) ; + } + break ; + + case 12 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: stats not present\n") ; + } + result = 0 ; /* stats not present */ + stats = (int *) NULL ; + break ; + + case 13 : + if (spumoni > 0) + { + mexPrintf ("colamdtest: ncol out of range\n") ; + } + result = 0 ; /* ncol out of range */ + n_col = -1 ; + break ; + + } + + + /* === Order the columns (destroys A) =================================== */ + + if (!colamd (n_row, n_col, Alen, A, p, knobs, stats)) + { + + /* return p = -1 if colamd failed */ + plhs [0] = mxCreateDoubleMatrix (1, 1, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + out_perm [0] = -1 ; + mxFree (p) ; + mxFree (A) ; + + if (spumoni > 0 || result) + { + colamd_report (stats) ; + } + + if (result) + { + mexErrMsgTxt ("colamd should have returned TRUE\n") ; + } + + return ; + /* mexErrMsgTxt ("colamd error!") ; */ + } + + if (!result) + { + colamd_report (stats) ; + mexErrMsgTxt ("colamd should have returned FALSE\n") ; + } + mxFree (A) ; + + /* === Return the permutation vector ==================================== */ + + plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + for (i = 0 ; i < n_col ; i++) + { + /* colamd is 0-based, but MATLAB expects this to be 1-based */ + out_perm [i] = p [i] + 1 ; + } + mxFree (p) ; + + /* === Return the stats vector ========================================== */ + + /* print stats if spumoni > 0 */ + if (spumoni > 0) + { + colamd_report (stats) ; + } + + if (nlhs == 2) + { + plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ; + out_stats = mxGetPr (plhs [1]) ; + for (i = 0 ; i < COLAMD_STATS ; i++) + { + out_stats [i] = stats [i] ; + } + + /* fix stats (5) and (6), for 1-based information on jumbled matrix. */ + /* note that this correction doesn't occur if symamd returns FALSE */ + out_stats [COLAMD_INFO1] ++ ; + out_stats [COLAMD_INFO2] ++ ; + } +} + + +static void dump_matrix +( + int A [ ], + int p [ ], + int n_row, + int n_col, + int Alen, + int limit +) +{ + int col, k, row ; + + mexPrintf ("dump matrix: nrow %d ncol %d Alen %d\n", n_row, n_col, Alen) ; + + for (col = 0 ; col < MIN (n_col, limit) ; col++) + { + mexPrintf ("column %d, p[col] %d, p [col+1] %d, length %d\n", + col, p [col], p [col+1], p [col+1] - p [col]) ; + for (k = p [col] ; k < p [col+1] ; k++) + { + row = A [k] ; + mexPrintf (" %d", row) ; + } + mexPrintf ("\n") ; + } +} diff --git a/liboctave/COLAMD/luflops.m b/liboctave/COLAMD/luflops.m new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/luflops.m @@ -0,0 +1,29 @@ +function fl = luflops (L, U) +% +% fl = luflops (L,U) +% +% Given a sparse LU factorization (L and U), return the flop count required +% by a conventional LU factorization algorithm to compute it. L and U can +% be either sparse or full matrices. L must be lower triangular and U must +% be upper triangular. Do not attempt to use this on the permuted L from +% [L,U] = lu (A). Instead, use [L,U,P] = lu (A) or [L,U,P,Q] = lu (A). +% +% Note that there is a subtle undercount in this estimate. Suppose A is +% completely dense, but during LU factorization exact cancellation occurs, +% causing some of the entries in L and U to become identically zero. The +% flop count returned by this routine is an undercount. There is a simple +% way to fix this (L = spones (L) + spones (tril (A))), but the fix is partial. +% It can also occur that some entry in L is a "symbolic" fill-in (zero in +% A, but a fill-in entry and thus must be computed), but numerically +% zero. The only way to get a reliable LU factorization would be to do a +% purely symbolic factorization of A. This cannot be done with +% symbfact (A, 'col'). +% +% See NA Digest, Vol 00, #50, Tuesday, Dec. 5, 2000 +% +% Tim Davis, Sept. 23, 2002. Written for MATLAB 6.5. + +Lnz = full (sum (spones (L))) - 1 ; % off diagonal nz in cols of L +Unz = full (sum (spones (U')))' - 1 ; % off diagonal nz in rows of U +fl = 2*Lnz*Unz + sum (Lnz) ; + diff --git a/liboctave/COLAMD/symamd.m b/liboctave/COLAMD/symamd.m new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/symamd.m @@ -0,0 +1,108 @@ +function [p, stats] = symamd (S, knobs) +%SYMAMD Symmetric approximate minimum degree permutation. +% P = SYMAMD (S) for a symmetric positive definite matrix S, returns the +% permutation vector p such that S(p,p) tends to have a sparser Cholesky +% factor than S. Sometimes SYMAMD works well for symmetric indefinite +% matrices too. SYMAMD tends to be faster than SYMMMD and tends to return +% a better ordering. The matrix S is assumed to be symmetric; only the +% strictly lower triangular part is referenced. S must be square. +% +% See also COLMMD, COLPERM, SPPARMS, COLAMD, SYMMMD, SYMRCM. +% +% Usage: P = symamd (S) +% P = symamd (S, knobs) +% [P, stats] = symamd (S) +% [P, stats] = symamd (S, knobs) +% +% knobs is an optional input argument. If S is n-by-n, then rows and +% columns with more than knobs(1)*n entries are removed prior to ordering, +% and ordered last in the output permutation P. If the knobs parameter is not +% present, then the default of 0.5 is used instead. knobs (2) controls the +% printing of statistics and error messages. +% +% stats is an optional 20-element output vector that provides data about the +% ordering and the validity of the input matrix S. Ordering statistics are +% in stats (1:3). stats (1) = stats (2) is the number of dense or empty +% rows and columns ignored by SYMAMD and stats (3) is the number of +% garbage collections performed on the internal data structure used by +% SYMAMD (roughly of size 8.4*nnz(tril(S,-1)) + 9*n integers). +% +% MATLAB built-in functions are intended to generate valid sparse matrices, +% with no duplicate entries, with ascending row indices of the nonzeros +% in each column, with a non-negative number of entries in each column (!) +% and so on. If a matrix is invalid, then SYMAMD may or may not be able +% to continue. If there are duplicate entries (a row index appears two or +% more times in the same column) or if the row indices in a column are out +% of order, then SYMAMD can correct these errors by ignoring the duplicate +% entries and sorting each column of its internal copy of the matrix S (the +% input matrix S is not repaired, however). If a matrix is invalid in other +% ways then SYMAMD cannot continue, an error message is printed, and no +% output arguments (P or stats) are returned. SYMAMD is thus a simple way +% to check a sparse matrix to see if it's valid. +% +% stats (4:7) provide information if SYMAMD was able to continue. The +% matrix is OK if stats (4) is zero, or 1 if invalid. stats (5) is the +% rightmost column index that is unsorted or contains duplicate entries, +% or zero if no such column exists. stats (6) is the last seen duplicate +% or out-of-order row index in the column index given by stats (5), or zero +% if no such row index exists. stats (7) is the number of duplicate or +% out-of-order row indices. +% +% stats (8:20) is always zero in the current version of SYMAMD (reserved +% for future use). +% +% The ordering is followed by a column elimination tree post-ordering. +% +% Authors: +% +% The authors of the code itself are Stefan I. Larimore and Timothy A. +% Davis (davis@cise.ufl.edu), University of Florida. The algorithm was +% developed in collaboration with John Gilbert, Xerox PARC, and Esmond +% Ng, Oak Ridge National Laboratory. +% +% Date: +% +% September 8, 2003. Version 2.3. +% +% Acknowledgements: +% +% This work was supported by the National Science Foundation, under +% grants DMS-9504974 and DMS-9803599. + +% Notice: +% Copyright (c) 1998-2003 by the University of Florida. +% All Rights Reserved. +% +% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c +% file) for the License. +% +% Availability: +% +% The colamd/symamd library is available at +% +% http://www.cise.ufl.edu/research/sparse/colamd/ +% + +%------------------------------------------------------------------------------- +% perform the symamd ordering: +%------------------------------------------------------------------------------- + +if (nargout <= 1 & nargin == 1) + p = symamdmex (S) ; +elseif (nargout <= 1 & nargin == 2) + p = symamdmex (S, knobs) ; +elseif (nargout == 2 & nargin == 1) + [p, stats] = symamdmex (S) ; +elseif (nargout == 2 & nargin == 2) + [p, stats] = symamdmex (S, knobs) ; +else + error ('symamd: incorrect number of input and/or output arguments') ; +end + +%------------------------------------------------------------------------------- +% symmetric elimination tree post-ordering: +%------------------------------------------------------------------------------- + +[ignore, q] = sparsfun ('symetree', S (p,p)) ; +p = p (q) ; + diff --git a/liboctave/COLAMD/symamdmex.c b/liboctave/COLAMD/symamdmex.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/symamdmex.c @@ -0,0 +1,241 @@ +/* ========================================================================== */ +/* === symamd mexFunction =================================================== */ +/* ========================================================================== */ + +/* + Usage: + + P = symamd (A) ; + + P = symamd (A, knobs) ; + + [ P, stats ] = symamd (A) ; + + [ P, stats ] = symamd (A, knobs) ; + + Returns a permutation vector P such that the Cholesky factorization of + A (P,P) tends to be sparser than that of A. This routine provides the same + functionality as SYMMMD, but tends to be much faster and tends to return a + better permutation vector. Note that the SYMMMD m-file in + MATLAB 5.2 also performs a symmetric elimination tree post-ordering. This + mexFunction does not do this post-ordering. This mexFunction is a + replacement for the p = sparsfun ('symmmd', A) operation. + + A must be square, and is assummed to have a symmetric nonzero pattern. + Only the nonzero pattern of the lower triangular portion of A is accessed. + This routine constructs a matrix M such that the nonzero pattern of M'M is + equal to A (assuming A has symmetric pattern), and then performs a column + ordering of M using colamd. + + The knobs and stats vectors are optional: + + knobs (1) rows and columns with more than (knobs(1))*n entries + are removed prior to ordering, and placed last in + the output ordering. If knobs is not present, then the + default of 0.5 is used. + + knobs (2) print level, similar to spparms ('spumoni') + + stats (1) the number of dense (or empty) rows and columms. These + are ordered last, in their natural order. + + stats (2) (same as stats (1)) + + stats (3) the number of garbage collections performed. + + stats (4) return status: + + 0: matrix is a valid MATLAB matrix. + + 1: matrix has duplicate entries or unsorted columns. + This should not occur in a valid MATLAB matrix, + but the ordering proceeded anyway by ignoring the + duplicate row indices in each column. See + stats (5:7) for more information. + + stats (5) highest numbered column that is unsorted or has + duplicate entries (zero if none) + + stats (6) last seen duplicate or unsorted row index + (zero if none) + + stats (7) number of duplicate or unsorted row indices + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Notice: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c + file) for the License. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/symamdmex.c + file. It requires the colamd.c and colamd.h files. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" +#include "mex.h" +#include "matrix.h" +#include + +/* ========================================================================== */ +/* === symamd mexFunction =================================================== */ +/* ========================================================================== */ + +void mexFunction +( + /* === Parameters ======================================================= */ + + int nlhs, /* number of left-hand sides */ + mxArray *plhs [], /* left-hand side matrices */ + int nrhs, /* number of right--hand sides */ + const mxArray *prhs [] /* right-hand side matrices */ +) +{ + /* === Local variables ================================================== */ + + int *perm ; /* column ordering of M and ordering of A */ + int *A ; /* row indices of input matrix A */ + int *p ; /* column pointers of input matrix A */ + int n_col ; /* number of columns of A */ + int n_row ; /* number of rows of A */ + int full ; /* TRUE if input matrix full, FALSE if sparse */ + double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */ + double *out_perm ; /* output permutation vector */ + double *out_stats ; /* output stats vector */ + double *in_knobs ; /* input knobs vector */ + int i ; /* loop counter */ + mxArray *Ainput ; /* input matrix handle */ + int spumoni ; /* verbosity variable */ + int stats [COLAMD_STATS] ; /* stats for symamd */ + + /* === Check inputs ===================================================== */ + + if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) + { + mexErrMsgTxt ( + "symamd: incorrect number of input and/or output arguments.") ; + } + + /* === Get knobs ======================================================== */ + + colamd_set_defaults (knobs) ; + spumoni = 0 ; + + /* check for user-passed knobs */ + if (nrhs == 2) + { + in_knobs = mxGetPr (prhs [1]) ; + i = mxGetNumberOfElements (prhs [1]) ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; + if (i > 1) spumoni = (int) in_knobs [1] ; + } + + /* print knob settings if spumoni > 0 */ + if (spumoni > 0) + { + mexPrintf ("symamd: dense row/col fraction: %f\n", + knobs [COLAMD_DENSE_ROW]) ; + } + + /* === If A is full, convert to a sparse matrix ========================= */ + + Ainput = (mxArray *) prhs [0] ; + if (mxGetNumberOfDimensions (Ainput) != 2) + { + mexErrMsgTxt ("symamd: input matrix must be 2-dimensional.") ; + } + full = !mxIsSparse (Ainput) ; + if (full) + { + mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ; + } + + /* === Allocate workspace for symamd ==================================== */ + + /* get size of matrix */ + n_row = mxGetM (Ainput) ; + n_col = mxGetN (Ainput) ; + if (n_col != n_row) + { + mexErrMsgTxt ("symamd: matrix must be square.") ; + } + + A = mxGetIr (Ainput) ; + p = mxGetJc (Ainput) ; + perm = (int *) mxCalloc (n_col+1, sizeof (int)) ; + + /* === Order the rows and columns of A (does not destroy A) ============= */ + + if (!symamd (n_col, A, p, perm, knobs, stats, &mxCalloc, &mxFree)) + { + symamd_report (stats) ; + mexErrMsgTxt ("symamd error!") ; + } + + if (full) + { + mxDestroyArray (Ainput) ; + } + + /* === Return the permutation vector ==================================== */ + + plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + for (i = 0 ; i < n_col ; i++) + { + /* symamd is 0-based, but MATLAB expects this to be 1-based */ + out_perm [i] = perm [i] + 1 ; + } + mxFree (perm) ; + + /* === Return the stats vector ========================================== */ + + /* print stats if spumoni > 0 */ + if (spumoni > 0) + { + symamd_report (stats) ; + } + + if (nlhs == 2) + { + plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ; + out_stats = mxGetPr (plhs [1]) ; + for (i = 0 ; i < COLAMD_STATS ; i++) + { + out_stats [i] = stats [i] ; + } + + /* fix stats (5) and (6), for 1-based information on jumbled matrix. */ + /* note that this correction doesn't occur if symamd returns FALSE */ + out_stats [COLAMD_INFO1] ++ ; + out_stats [COLAMD_INFO2] ++ ; + } +} diff --git a/liboctave/COLAMD/symamdtestmex.c b/liboctave/COLAMD/symamdtestmex.c new file mode 100644 --- /dev/null +++ b/liboctave/COLAMD/symamdtestmex.c @@ -0,0 +1,575 @@ +/* ========================================================================== */ +/* === symamdtest mexFunction =============================================== */ +/* ========================================================================== */ + +/* + This MATLAB mexFunction is for testing only. It is not meant for + production use. See symamdmex.c instead. + + Usage: + + [ P, stats ] = symamdtest (A, knobs) ; + + Returns a permutation vector P such that the Cholesky factorization of + A (P,P) tends to be sparser than that of A. This routine provides the same + functionality as SYMMMD, but tends to be much faster and tends to return a + better permutation vector. Note that the SYMMMD m-file in + MATLAB 5.2 also performs a symmetric elimination tree post-ordering. This + mexFunction does not do this post-ordering. This mexFunction is a + replacement for the p = sparsfun ('symmmd', A) operation. + + A must be square, and is assummed to have a symmetric nonzero pattern. + Only the nonzero pattern of the lower triangular portion of A is accessed. + This routine constructs a matrix M such that the nonzero pattern of M'M is + equal to A (assuming A has symmetric pattern), and then performs a column + ordering of M using colamd. + + The knobs and stats vectors are optional: + + knobs (1) rows and columns with more than (knobs(1))*n entries + are removed prior to ordering, and placed last in + the output ordering. If knobs is not present, then the + default of 0.5 is used. + + knobs (2) print level, similar to spparms ('spumoni') + + knobs (3) for testing only. Controls how the input matrix is + jumbled prior to calling symamd, to test its error + handling capability. + + stats (1) the number of dense (or empty) rows and columms. These + are ordered last, in their natural order. + + stats (2) (same as stats (1)) + + stats (3) the number of garbage collections performed. + + stats (4) return status: + + 0: matrix is a valid MATLAB matrix. + + 1: matrix has duplicate entries or unsorted columns. + This should not occur in a valid MATLAB matrix, + but the ordering proceeded anyway by ignoring the + duplicate row indices in each column. See + stats (5:7) for more information. + + stats (5) highest numbered column that is unsorted or has + duplicate entries (zero if none) + + stats (6) last seen duplicate or unsorted row index + (zero if none) + + stats (7) number of duplicate or unsorted row indices + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Date: + + September 8, 2003. Version 2.3. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Notice: + + Copyright (c) 1998-2003 by the University of Florida. + All Rights Reserved. + + See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c + file) for the License. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the + http://www.cise.ufl.edu/research/sparse/colamd/symamdtestmex.c + file. It requires the colamd.c and colamd.h files. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" +#include "mex.h" +#include "matrix.h" +#include +#include + +static void dump_matrix +( + int A [ ], + int p [ ], + int n_row, + int n_col, + int Alen, + int limit +) ; + +/* ========================================================================== */ +/* === symamd mexFunction =================================================== */ +/* ========================================================================== */ + +void mexFunction +( + /* === Parameters ======================================================= */ + + int nlhs, /* number of left-hand sides */ + mxArray *plhs [], /* left-hand side matrices */ + int nrhs, /* number of right--hand sides */ + const mxArray *prhs [] /* right-hand side matrices */ +) +{ + /* === Local variables ================================================== */ + + int *perm ; /* column ordering of M and ordering of A */ + int *A ; /* row indices of input matrix A */ + int *p ; /* column pointers of input matrix A */ + int n_col ; /* number of columns of A */ + int n_row ; /* number of rows of A */ + int full ; /* TRUE if input matrix full, FALSE if sparse */ + double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */ + double *out_perm ; /* output permutation vector */ + double *out_stats ; /* output stats vector */ + double *in_knobs ; /* input knobs vector */ + int i ; /* loop counter */ + mxArray *Ainput ; /* input matrix handle */ + int spumoni ; /* verbosity variable */ + int stats2 [COLAMD_STATS] ; /* stats for symamd */ + + int *cp, *cp_end, result, nnz, col, length ; + int *stats ; + stats = stats2 ; + + /* === Check inputs ===================================================== */ + + if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) + { + mexErrMsgTxt ( + "symamd: incorrect number of input and/or output arguments.") ; + } + + if (nrhs != 2) + { + mexErrMsgTxt ("symamdtest: knobs are required") ; + } + /* for testing we require all 3 knobs */ + if (mxGetNumberOfElements (prhs [1]) < 3) + { + mexErrMsgTxt ("symamdtest: must have all 3 knobs for testing") ; + } + + /* === Get knobs ======================================================== */ + + colamd_set_defaults (knobs) ; + spumoni = 0 ; + + /* check for user-passed knobs */ + if (nrhs == 2) + { + in_knobs = mxGetPr (prhs [1]) ; + i = mxGetNumberOfElements (prhs [1]) ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; + if (i > 1) spumoni = (int) in_knobs [1] ; + } + + /* print knob settings if spumoni > 0 */ + if (spumoni > 0) + { + mexPrintf ("symamd: dense row/col fraction: %f\n", + knobs [COLAMD_DENSE_ROW]) ; + } + + /* === If A is full, convert to a sparse matrix ========================= */ + + Ainput = (mxArray *) prhs [0] ; + if (mxGetNumberOfDimensions (Ainput) != 2) + { + mexErrMsgTxt ("symamd: input matrix must be 2-dimensional.") ; + } + full = !mxIsSparse (Ainput) ; + if (full) + { + mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ; + } + + /* === Allocate workspace for symamd ==================================== */ + + /* get size of matrix */ + n_row = mxGetM (Ainput) ; + n_col = mxGetN (Ainput) ; + if (n_col != n_row) + { + mexErrMsgTxt ("symamd: matrix must be square.") ; + } + + /* p = mxGetJc (Ainput) ; */ + p = (int *) mxCalloc (n_col+1, sizeof (int)) ; + (void) memcpy (p, mxGetJc (Ainput), (n_col+1)*sizeof (int)) ; + + nnz = p [n_col] ; + if (spumoni > 0) + { + mexPrintf ("symamdtest: nnz %d\n", nnz) ; + } + + /* A = mxGetIr (Ainput) ; */ + A = (int *) mxCalloc (nnz+1, sizeof (int)) ; + (void) memcpy (A, mxGetIr (Ainput), nnz*sizeof (int)) ; + + perm = (int *) mxCalloc (n_col+1, sizeof (int)) ; + +/* === Jumble matrix ======================================================== */ + + +/* + knobs [2] FOR TESTING ONLY: Specifies how to jumble matrix + 0 : No jumbling + 1 : (no errors) + 2 : Make first pointer non-zero + 3 : Make column pointers not non-decreasing + 4 : (no errors) + 5 : Make row indices not strictly increasing + 6 : Make a row index greater or equal to n_row + 7 : Set A = NULL + 8 : Set p = NULL + 9 : Repeat row index + 10: make row indices not sorted + 11: jumble columns massively (note this changes + the pattern of the matrix A.) + 12: Set stats = NULL + 13: Make n_col less than zero +*/ + + /* jumble appropriately */ + switch ((int) in_knobs [2]) + { + + case 0 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: no errors expected\n") ; + } + result = 1 ; /* no errors */ + break ; + + case 1 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: no errors expected (1)\n") ; + } + result = 1 ; + break ; + + case 2 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: p [0] nonzero\n") ; + } + result = 0 ; /* p [0] must be zero */ + p [0] = 1 ; + break ; + + case 3 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: negative length last column\n") ; + } + result = (n_col == 0) ; /* p must be monotonically inc. */ + p [n_col] = p [0] ; + break ; + + case 4 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: no errors expected (4)\n") ; + } + result = 1 ; + break ; + + case 5 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: row index out of range (-1)\n") ; + } + if (nnz > 0) /* row index out of range */ + { + result = 0 ; + A [nnz-1] = -1 ; + } + else + { + if (spumoni > 0) + { + mexPrintf ("Note: no row indices to put out of range\n") ; + } + result = 1 ; + } + break ; + + case 6 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: row index out of range (ncol)\n") ; + } + if (nnz > 0) /* row index out of range */ + { + result = 0 ; + A [nnz-1] = n_col ; + } + else + { + if (spumoni > 0) + { + mexPrintf ("Note: no row indices to put out of range\n") ; + } + result = 1 ; + } + break ; + + case 7 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: A not present\n") ; + } + result = 0 ; /* A not present */ + A = (int *) NULL ; + break ; + + case 8 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: p not present\n") ; + } + result = 0 ; /* p not present */ + p = (int *) NULL ; + break ; + + case 9 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: duplicate row index\n") ; + } + result = 1 ; /* duplicate row index */ + + for (col = 0 ; col < n_col ; col++) + { + length = p [col+1] - p [col] ; + if (length > 1) + { + A [p [col+1]-2] = A [p [col+1] - 1] ; + if (spumoni > 0) + { + mexPrintf ("Made duplicate row %d in col %d\n", + A [p [col+1] - 1], col) ; + } + break ; + } + } + + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, nnz, col+2) ; + } + break ; + + case 10 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: unsorted column\n") ; + } + result = 1 ; /* jumbled columns */ + + for (col = 0 ; col < n_col ; col++) + { + length = p [col+1] - p [col] ; + if (length > 1) + { + i = A[p [col]] ; + A [p [col]] = A[p [col] + 1] ; + A [p [col] + 1] = i ; + if (spumoni > 0) + { + mexPrintf ("Unsorted column %d \n", col) ; + } + break ; + } + } + + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, nnz, col+2) ; + } + break ; + + case 11 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: massive jumbling\n") ; + } + result = 1 ; /* massive jumbling, but no errors */ + srand (1) ; + for (i = 0 ; i < n_col ; i++) + { + cp = &A [p [i]] ; + cp_end = &A [p [i+1]] ; + while (cp < cp_end) + { + *cp++ = rand() % n_row ; + } + } + if (spumoni > 1) + { + dump_matrix (A, p, n_row, n_col, nnz, n_col) ; + } + break ; + + case 12 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: stats not present\n") ; + } + result = 0 ; /* stats not present */ + stats = (int *) NULL ; + break ; + + case 13 : + if (spumoni > 0) + { + mexPrintf ("symamdtest: ncol out of range\n") ; + } + result = 0 ; /* ncol out of range */ + n_col = -1 ; + break ; + + } + + /* === Order the rows and columns of A (does not destroy A) ============= */ + + if (!symamd (n_col, A, p, perm, knobs, stats, &mxCalloc, &mxFree)) + { + + /* return p = -1 if colamd failed */ + plhs [0] = mxCreateDoubleMatrix (1, 1, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + out_perm [0] = -1 ; + mxFree (p) ; + mxFree (A) ; + + if (spumoni > 0 || result) + { + symamd_report (stats) ; + } + + if (result) + { + mexErrMsgTxt ("symamd should have returned TRUE\n") ; + } + + return ; + /* mexErrMsgTxt ("symamd error!") ; */ + } + + if (!result) + { + symamd_report (stats) ; + mexErrMsgTxt ("symamd should have returned FALSE\n") ; + } + + if (full) + { + mxDestroyArray (Ainput) ; + } + + /* === Return the permutation vector ==================================== */ + + plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ; + out_perm = mxGetPr (plhs [0]) ; + for (i = 0 ; i < n_col ; i++) + { + /* symamd is 0-based, but MATLAB expects this to be 1-based */ + out_perm [i] = perm [i] + 1 ; + } + mxFree (perm) ; + + /* === Return the stats vector ========================================== */ + + /* print stats if spumoni > 0 */ + if (spumoni > 0) + { + symamd_report (stats) ; + } + + if (nlhs == 2) + { + plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ; + out_stats = mxGetPr (plhs [1]) ; + for (i = 0 ; i < COLAMD_STATS ; i++) + { + out_stats [i] = stats [i] ; + } + + /* fix stats (5) and (6), for 1-based information on jumbled matrix. */ + /* note that this correction doesn't occur if symamd returns FALSE */ + out_stats [COLAMD_INFO1] ++ ; + out_stats [COLAMD_INFO2] ++ ; + } +} + + +#ifdef MIN +#undef MIN +#endif +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + + +static void dump_matrix +( + int A [ ], + int p [ ], + int n_row, + int n_col, + int Alen, + int limit +) +{ + int col, k, row ; + + mexPrintf ("dump matrix: nrow %d ncol %d Alen %d\n", n_row, n_col, Alen) ; + + if (!A) + { + mexPrintf ("A not present\n") ; + return ; + } + + if (!p) + { + mexPrintf ("p not present\n") ; + return ; + } + + for (col = 0 ; col < MIN (n_col, limit) ; col++) + { + mexPrintf ("column %d, p[col] %d, p [col+1] %d, length %d\n", + col, p [col], p [col+1], p [col+1] - p [col]) ; + for (k = p [col] ; k < p [col+1] ; k++) + { + row = A [k] ; + mexPrintf (" %d", row) ; + } + mexPrintf ("\n") ; + } +} diff --git a/liboctave/CSparse.cc b/liboctave/CSparse.cc new file mode 100644 --- /dev/null +++ b/liboctave/CSparse.cc @@ -0,0 +1,6496 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "quit.h" +#include "lo-ieee.h" +#include "lo-mappers.h" +#include "f77-fcn.h" +#include "dRowVector.h" + +#include "CSparse.h" +#include "boolSparse.h" +#include "dSparse.h" +#include "oct-spparms.h" +#include "SparseCmplxLU.h" + +// External UMFPACK functions in C +extern "C" { +#include "umfpack.h" +} + +// Fortran functions we call. +extern "C" +{ + F77_RET_T + F77_FUNC (zgbtrf, ZGBTRF) (const int&, const int&, const int&, + const int&, Complex*, const int&, int*, int&); + + F77_RET_T + F77_FUNC (zgbtrs, ZGBTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, const int&, + const Complex*, const int&, + const int*, Complex*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zgbcon, ZGBCON) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, Complex*, + const int&, const int*, const double&, + double&, Complex*, double*, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zpbtrf, ZPBTRF) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, Complex*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zpbtrs, ZPBTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, Complex*, const int&, + Complex*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zpbcon, ZPBCON) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, Complex*, const int&, + const double&, double&, Complex*, int*, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zgttrf, ZGTTRF) (const int&, Complex*, Complex*, Complex*, + Complex*, int*, int&); + + F77_RET_T + F77_FUNC (zgttrs, ZGTTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const Complex*, const Complex*, + const Complex*, const Complex*, const int*, + Complex *, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zptsv, ZPTSV) (const int&, const int&, Complex*, Complex*, + Complex*, const int&, int&); + + F77_RET_T + F77_FUNC (zgtsv, ZGTSV) (const int&, const int&, Complex*, Complex*, + Complex*, Complex*, const int&, int&); +} + +SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a) + : MSparse (a.rows (), a.cols (), a.nnz ()) +{ + int nc = cols (); + int nz = nnz (); + + for (int i = 0; i < nc + 1; i++) + cidx (i) = a.cidx (i); + + for (int i = 0; i < nz; i++) + { + data (i) = a.data (i); + ridx (i) = a.ridx (i); + } +} + +SparseComplexMatrix::SparseComplexMatrix (const SparseBoolMatrix& a) + : MSparse (a.rows (), a.cols (), a.nnz ()) +{ + int nc = cols (); + int nz = nnz (); + + for (int i = 0; i < nc + 1; i++) + cidx (i) = a.cidx (i); + + for (int i = 0; i < nz; i++) + { + data (i) = a.data (i); + ridx (i) = a.ridx (i); + } +} + +bool +SparseComplexMatrix::operator == (const SparseComplexMatrix& a) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + int nr_a = a.rows (); + int nc_a = a.cols (); + int nz_a = a.nnz (); + + if (nr != nr_a || nc != nc_a || nz != nz_a) + return false; + + for (int i = 0; i < nc + 1; i++) + if (cidx(i) != a.cidx(i)) + return false; + + for (int i = 0; i < nz; i++) + if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) + return false; + + return true; +} + +bool +SparseComplexMatrix::operator != (const SparseComplexMatrix& a) const +{ + return !(*this == a); +} + +bool +SparseComplexMatrix::is_hermitian (void) const +{ + int nr = rows (); + int nc = cols (); + + if (is_square () && nr > 0) + { + for (int i = 0; i < nr; i++) + for (int j = i; j < nc; j++) + if (elem (i, j) != conj (elem (j, i))) + return false; + + return true; + } + + return false; +} + +static const Complex Complex_NaN_result (octave_NaN, octave_NaN); + +SparseComplexMatrix +SparseComplexMatrix::max (int dim) const +{ + Array2 dummy_idx; + return max (dummy_idx, dim); +} + +SparseComplexMatrix +SparseComplexMatrix::max (Array2& idx_arg, int dim) const +{ + SparseComplexMatrix result; + dim_vector dv = dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return result; + + int nr = dv(0); + int nc = dv(1); + + if (dim == 0) + { + idx_arg.resize (1, nc); + int nel = 0; + for (int j = 0; j < nc; j++) + { + Complex tmp_max; + double abs_max = octave_NaN; + int idx_j = 0; + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) != idx_j) + break; + else + idx_j++; + } + + if (idx_j != nr) + { + tmp_max = 0.; + abs_max = 0.; + } + + for (int i = cidx(j); i < cidx(j+1); i++) + { + Complex tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + + double abs_tmp = ::abs (tmp); + + if (octave_is_NaN_or_NA (abs_max) || abs_tmp > abs_max) + { + idx_j = ridx (i); + tmp_max = tmp; + abs_max = abs_tmp; + } + } + + idx_arg.elem (j) = octave_is_NaN_or_NA (tmp_max) ? 0 : idx_j; + if (abs_max != 0.) + nel++; + } + + result = SparseComplexMatrix (1, nc, nel); + + int ii = 0; + result.xcidx (0) = 0; + for (int j = 0; j < nc; j++) + { + Complex tmp = elem (idx_arg(j), j); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = 0; + } + result.xcidx (j+1) = ii; + } + } + else + { + idx_arg.resize (nr, 1, 0); + + for (int i = cidx(0); i < cidx(1); i++) + idx_arg.elem(ridx(i)) = -1; + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (idx_arg.elem(i) != -1) + continue; + bool found = false; + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + found = true; + break; + } + + if (!found) + idx_arg.elem(i) = j; + + } + + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ir = ridx (i); + int ix = idx_arg.elem (ir); + Complex tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (ix == -1 || ::abs(tmp) > ::abs(elem (ir, ix))) + idx_arg.elem (ir) = j; + } + } + + int nel = 0; + for (int j = 0; j < nr; j++) + if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) + nel++; + + result = SparseComplexMatrix (nr, 1, nel); + + int ii = 0; + result.xcidx (0) = 0; + result.xcidx (1) = nel; + for (int j = 0; j < nr; j++) + { + if (idx_arg(j) == -1) + { + idx_arg(j) = 0; + result.xdata (ii) = Complex_NaN_result; + result.xridx (ii++) = j; + } + else + { + Complex tmp = elem (j, idx_arg(j)); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = j; + } + } + } + } + + return result; +} + +SparseComplexMatrix +SparseComplexMatrix::min (int dim) const +{ + Array2 dummy_idx; + return min (dummy_idx, dim); +} + +SparseComplexMatrix +SparseComplexMatrix::min (Array2& idx_arg, int dim) const +{ + SparseComplexMatrix result; + dim_vector dv = dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return result; + + int nr = dv(0); + int nc = dv(1); + + if (dim == 0) + { + idx_arg.resize (1, nc); + int nel = 0; + for (int j = 0; j < nc; j++) + { + Complex tmp_min; + double abs_min = octave_NaN; + int idx_j = 0; + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) != idx_j) + break; + else + idx_j++; + } + + if (idx_j != nr) + { + tmp_min = 0.; + abs_min = 0.; + } + + for (int i = cidx(j); i < cidx(j+1); i++) + { + Complex tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + + double abs_tmp = ::abs (tmp); + + if (octave_is_NaN_or_NA (abs_min) || abs_tmp < abs_min) + { + idx_j = ridx (i); + tmp_min = tmp; + abs_min = abs_tmp; + } + } + + idx_arg.elem (j) = octave_is_NaN_or_NA (tmp_min) ? 0 : idx_j; + if (abs_min != 0.) + nel++; + } + + result = SparseComplexMatrix (1, nc, nel); + + int ii = 0; + result.xcidx (0) = 0; + for (int j = 0; j < nc; j++) + { + Complex tmp = elem (idx_arg(j), j); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = 0; + } + result.xcidx (j+1) = ii; + } + } + else + { + idx_arg.resize (nr, 1, 0); + + for (int i = cidx(0); i < cidx(1); i++) + idx_arg.elem(ridx(i)) = -1; + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (idx_arg.elem(i) != -1) + continue; + bool found = false; + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + found = true; + break; + } + + if (!found) + idx_arg.elem(i) = j; + + } + + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ir = ridx (i); + int ix = idx_arg.elem (ir); + Complex tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (ix == -1 || ::abs(tmp) < ::abs(elem (ir, ix))) + idx_arg.elem (ir) = j; + } + } + + int nel = 0; + for (int j = 0; j < nr; j++) + if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) + nel++; + + result = SparseComplexMatrix (nr, 1, nel); + + int ii = 0; + result.xcidx (0) = 0; + result.xcidx (1) = nel; + for (int j = 0; j < nr; j++) + { + if (idx_arg(j) == -1) + { + idx_arg(j) = 0; + result.xdata (ii) = Complex_NaN_result; + result.xridx (ii++) = j; + } + else + { + Complex tmp = elem (j, idx_arg(j)); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = j; + } + } + } + } + + return result; +} + +// destructive insert/delete/reorder operations + +SparseComplexMatrix& +SparseComplexMatrix::insert (const SparseMatrix& a, int r, int c) +{ + SparseComplexMatrix tmp (a); + return insert (a, r, c); +} + +SparseComplexMatrix& +SparseComplexMatrix::insert (const SparseComplexMatrix& a, int r, int c) +{ + MSparse::insert (a, r, c); + return *this; +} + +SparseComplexMatrix +SparseComplexMatrix::concat (const SparseComplexMatrix& rb, + const Array& ra_idx) +{ + // Don't use numel to avoid all possiblity of an overflow + if (rb.rows () > 0 && rb.cols () > 0) + insert (rb, ra_idx(0), ra_idx(1)); + return *this; +} + +SparseComplexMatrix +SparseComplexMatrix::concat (const SparseMatrix& rb, const Array& ra_idx) +{ + SparseComplexMatrix tmp (rb); + if (rb.rows () > 0 && rb.cols () > 0) + insert (tmp, ra_idx(0), ra_idx(1)); + return *this; +} + +ComplexMatrix +SparseComplexMatrix::matrix_value (void) const +{ + int nr = rows (); + int nc = cols (); + ComplexMatrix retval (nr, nc, Complex (0.0, 0.0)); + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + retval.elem (ridx(i), j) = data (i); + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::hermitian (void) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + SparseComplexMatrix retval (nc, nr, nz); + + retval.cidx(0) = 0; + for (int i = 0, iidx = 0; i < nr; i++) + { + for (int j = 0; j < nc; j++) + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + retval.data(iidx) = conj (data(k)); + retval.ridx(iidx++) = j; + } + retval.cidx(i+1) = iidx; + } + + return retval; +} + +SparseComplexMatrix +conj (const SparseComplexMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + SparseComplexMatrix retval (nc, nr, nz); + + for (int i = 0; i < nc + 1; i++) + retval.cidx (i) = a.cidx (i); + + for (int i = 0; i < nz; i++) + { + retval.data (i) = conj (a.data (i)); + retval.ridx (i) = a.ridx (i); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::inverse (void) const +{ + int info; + double rcond; + return inverse (info, rcond, 0, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::inverse (int& info) const +{ + double rcond; + return inverse (info, rcond, 0, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::inverse (int& info, double& rcond, int force, + int calc_cond) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::inverse not implemented yet"); + return SparseComplexMatrix (); +} + +ComplexDET +SparseComplexMatrix::determinant (void) const +{ + int info; + double rcond; + return determinant (info, rcond, 0); +} + +ComplexDET +SparseComplexMatrix::determinant (int& info) const +{ + double rcond; + return determinant (info, rcond, 0); +} + +ComplexDET +SparseComplexMatrix::determinant (int& err, double& rcond, int calc_cond) const +{ + ComplexDET retval; + + int nr = rows (); + int nc = cols (); + + if (nr == 0 || nc == 0 || nr != nc) + { + Complex d[2]; + d[0] = 1.0; + d[1] = 0.0; + retval = ComplexDET (d); + } + else + { + err = 0; + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_zi_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_zi_report_control (control); + + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + + umfpack_zi_report_matrix (nr, nc, Ap, Ai, + X_CAST (const double *, Ax), + NULL, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_zi_qsymbolic + (nr, nc, Ap, Ai, X_CAST (const double *, Ax), NULL, + NULL, &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::determinant symbolic factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + umfpack_zi_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_zi_numeric (Ap, Ai, X_CAST (const double *, Ax), + NULL, Symbolic, &Numeric, + control, info) ; + umfpack_zi_free_symbolic (&Symbolic) ; + + rcond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::determinant numeric factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + { + umfpack_zi_report_numeric (Numeric, control); + + Complex d[2]; + double d_exponent; + + status = umfpack_zi_get_determinant + (X_CAST (double *, &d[0]), NULL, &d_exponent, + Numeric, info); + d[1] = d_exponent; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::determinant error calculating determinant"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + retval = ComplexDET (d); + } + } + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::dsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, solve_singularity_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + retval.resize (b.rows (), b.cols()); + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(i,j) / data (i); + else + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(ridx(i),j) / data (i); + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = ::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::dsolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, solve_singularity_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + + retval.xcidx(0) = 0; + int ii = 0; + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + { + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + retval.xridx (ii) = b.ridx(i); + retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); + } + retval.xcidx(j+1) = ii; + } + else + for (int j = 0; j < b.cols(); j++) + { + for (int i = 0; i < nr; i++) + { + bool found = false; + int k; + for (k = b.cidx(j); k < b.cidx(j+1); k++) + if (ridx(i) == b.ridx(k)) + { + found = true; + break; + } + if (found) + { + retval.xridx (ii) = i; + retval.xdata (ii++) = b.data(k) / data (i); + } + } + retval.xcidx(j+1) = ii; + } + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = ::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, solve_singularity_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + retval.resize (b.rows (), b.cols()); + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(i,j) / data (i); + else + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(ridx(i),j) / data (i); + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = ::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + + retval.xcidx(0) = 0; + int ii = 0; + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + { + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + retval.xridx (ii) = b.ridx(i); + retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); + } + retval.xcidx(j+1) = ii; + } + else + for (int j = 0; j < b.cols(); j++) + { + for (int i = 0; i < nr; i++) + { + bool found = false; + int k; + for (k = b.cidx(j); k < b.cidx(j+1); k++) + if (ridx(i) == b.ridx(k)) + { + found = true; + break; + } + if (found) + { + retval.xridx (ii) = i; + retval.xdata (ii++) = b.data(k) / data (i); + } + } + retval.xcidx(j+1) = ii; + } + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = ::abs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::utsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_cols = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Upper) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_cols; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = ComplexMatrix (b); + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_cols; j++) + { + int offset = j * nr; + for (int k = nr-1; k >= 0; k--) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k+1)-1); + x_vec[k+offset] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::utsolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Upper) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + if (work[k] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + return retval; +} + +ComplexMatrix +SparseComplexMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_nc = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Upper) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_nc; j++) + { + int offset = j * nr; + for (int k = nr-1; k >= 0; k--) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k+1)-1); + x_vec[k+offset] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Upper) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + if (work[k] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::ltsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_cols = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Lower) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_cols; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = ComplexMatrix (b); + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_cols; j++) + { + int offset = j * nr; + for (int k = 0; k < nr; k++) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k)); + x_vec[k+offset] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Lower) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + if (work[k] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_nc = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Lower) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_nc; j++) + { + int offset = j * nr; + for (int k = 0; k < nr; k++) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k)); + x_vec[k+offset] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += ::abs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Lower) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseComplexMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + if (work[k] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += ::abs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::trisolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii); + ii += 2; + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + } + } + + int b_nc = b.cols(); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, + b.rows(), err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zptsv"); + else if (err != 0) + { + err = 0; + mattype.mark_as_unsymmetric (); + typ = SparseType::Tridiagonal; + } + else + rcond = 1.; + } + + if (typ == SparseType::Tridiagonal) + { + OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + int b_nc = b.cols(); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, + b.rows(), err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgtsv"); + else if (err != 0) + { + rcond = 0.; + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + rcond = 1.; + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); + OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgttrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (zgttrs, ZGTTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, 1, DL, D, DU, DU2, pipvt, + work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgttrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii); + ii += 2; + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + } + } + + int b_nr = b.rows (); + int b_nc = b.cols(); + rcond = 1.; + + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, + b_nr, err)); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zptsv"); + err = -1; + } + else if (err != 0) + { + err = 0; + mattype.mark_as_unsymmetric (); + typ = SparseType::Tridiagonal; + } + } + + if (typ == SparseType::Tridiagonal) + { + OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + int b_nr = b.rows(); + int b_nc = b.cols(); + rcond = 1.; + + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, + b_nr, err)); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgtsv"); + err = -1; + } + else if (err != 0) + { + rcond = 0.; + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::trisolve (SparseType &mattype, + const SparseComplexMatrix& b, int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (Complex, DU2, nr - 2); + OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + F77_XFCN (zgttrf, ZGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgttrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + } + else + { + rcond = 1.; + char job = 'N'; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + Bx[i] = b (i,j); + + F77_XFCN (zgttrs, ZGTTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, 1, DL, D, DU, DU2, pipvt, + Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgttrs"); + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + + err = -1; + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = Bx[i]; + } + + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::bsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + // Calculate the norm of the matrix, for later use. + // double anorm = m_band.abs().sum().row(0).max(); + + char job = 'L'; + F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + // Unfortunately, the time to calculate the condition + // number is dominant for narrow banded matrices and + // so we rely on the "err" flag from xPBTRF to flag + // singularity. The commented code below is left here + // for reference + + //Array z (3 * nr); + //Complex *pz = z.fortran_vec (); + //Array iz (nr); + //int *piz = iz.fortran_vec (); + // + //F77_XFCN (zpbcon, ZGBCON, + // (F77_CONST_CHAR_ARG2 (&job, 1), + // nr, n_lower, tmp_data, ldm, + // anorm, rcond, pz, piz, err + // F77_CHAR_ARG_LEN (1))); + // + // + //if (f77_exception_encountered) + // (*current_liboctave_error_handler) + // ("unrecoverable error in zpbcon"); + // + //if (err != 0) + // err = -2; + // + //volatile double rcond_plus_one = rcond + 1.0; + // + //if (rcond_plus_one == 1.0 || xisnan (rcond)) + // { + // err = -2; + // + // if (sing_handler) + // sing_handler (rcond); + // else + // (*current_liboctave_error_handler) + // ("matrix singular to machine precision, rcond = %g", + // rcond); + // } + //else + // REST OF CODE, EXCEPT rcond=1 + + rcond = 1.; + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + int b_nc = b.cols (); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + } + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrf"); + else + { + // Throw-away extra info LAPACK gives so as to not + // change output. + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = '1'; + + // Unfortunately, the time to calculate the condition + // number is dominant for narrow banded matrices and + // so we rely on the "err" flag from xPBTRF to flag + // singularity. The commented code below is left here + // for reference + + //F77_XFCN (zgbcon, ZGBCON, + // (F77_CONST_CHAR_ARG2 (&job, 1), + // nc, n_lower, n_upper, tmp_data, ldm, pipvt, + // anorm, rcond, pz, piz, err + // F77_CHAR_ARG_LEN (1))); + // + //if (f77_exception_encountered) + // (*current_liboctave_error_handler) + // ("unrecoverable error in zgbcon"); + // + // if (err != 0) + // err = -2; + // + //volatile double rcond_plus_one = rcond + 1.0; + // + //if (rcond_plus_one == 1.0 || xisnan (rcond)) + // { + // err = -2; + // + // if (sing_handler) + // sing_handler (rcond); + // else + // (*current_liboctave_error_handler) + // ("matrix singular to machine precision, rcond = %g", + // rcond); + // } + //else + // REST OF CODE, EXCEPT rcond=1 + + rcond = 1.; + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + int b_nc = b.cols (); + + job = 'N'; + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrs"); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + err = -1; + break; + } + + for (int i = 0; i < b_nr; i++) + { + Complex tmp = Bx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + err = -1; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + err = -1; + } + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + int b_nc = b.cols (); + retval = ComplexMatrix (b); + Complex *result = retval.fortran_vec (); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + } + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (zpbtrf, ZPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + Bx[i] = b (i,j); + + F77_XFCN (zpbtrs, ZPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = Bx[i]; + } + + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + ComplexMatrix m_band (ldm, nc); + Complex *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (zgbtrf, ZGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in xgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, Bx, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + Bx[i] = 0.; + + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + Bx[b.ridx(i)] = b.data(i); + + F77_XFCN (zgbtrs, ZGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = Bx[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +void * +SparseComplexMatrix::factorize (int& err, double &rcond, Matrix &Control, + Matrix &Info, + solve_singularity_handler sing_handler) const +{ + // The return values + void *Numeric; + err = 0; + + // Setup the control parameters + Control = Matrix (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_zi_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + umfpack_zi_report_control (control); + + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + int nr = rows (); + int nc = cols (); + + umfpack_zi_report_matrix (nr, nc, Ap, Ai, X_CAST (const double *, Ax), + NULL, 1, control); + + void *Symbolic; + Info = Matrix (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_zi_qsymbolic (nr, nc, Ap, Ai, + X_CAST (const double *, Ax), + NULL, NULL, &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve symbolic factorization failed"); + err = -1; + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + umfpack_zi_report_symbolic (Symbolic, control); + + status = umfpack_zi_numeric (Ap, Ai, X_CAST (const double *, Ax), NULL, + Symbolic, &Numeric, control, info) ; + umfpack_zi_free_symbolic (&Symbolic) ; + +#ifdef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + umfpack_zi_report_numeric (Numeric, control); + + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } + else +#endif + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve numeric factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + err = -1; + } + else + { + umfpack_zi_report_numeric (Numeric, control); + } + } + + if (err != 0) + umfpack_zi_free_numeric (&Numeric); + + return Numeric; +} + +ComplexMatrix +SparseComplexMatrix::fsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + const double *Bx = b.fortran_vec (); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + for (int i = 0; i < b_nr; i++) + Bz[i] = 0.; + + retval.resize (b_nr, b_nc); + Complex *Xx = retval.fortran_vec (); + + for (int j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) + { + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, + X_CAST (const double *, Ax), + NULL, + X_CAST (double *, &Xx[iidx]), + NULL, + &Bx[iidx], Bz, Numeric, + control, info); + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + + umfpack_zi_report_status (control, status); + + err = -1; + + break; + } + } + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + for (int i = 0; i < b_nr; i++) + Bz[i] = 0.; + + // Take a first guess that the number of non-zero terms + // will be as many as in b + int x_nz = b.nnz (); + int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); + + retval.xcidx(0) = 0; + for (int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, + X_CAST (const double *, Ax), + NULL, + X_CAST (double *, Xx), NULL, + Bx, Bz, Numeric, control, + info); + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + + umfpack_zi_report_status (control, status); + + err = -1; + + break; + } + + for (int i = 0; i < b_nr; i++) + { + Complex tmp = Xx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + const Complex *Bx = b.fortran_vec (); + + retval.resize (b_nr, b_nc); + Complex *Xx = retval.fortran_vec (); + + for (int j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) + { + status = + umfpack_zi_solve (UMFPACK_A, Ap, Ai, + X_CAST (const double *, Ax), + NULL, X_CAST (double *, &Xx[iidx]), + NULL, X_CAST (const double *, &Bx[iidx]), + NULL, Numeric, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + + umfpack_zi_report_status (control, status); + + err = -1; + + break; + } + } + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const Complex *Ax = data (); + + OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + int x_nz = b.nnz (); + int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); + + retval.xcidx(0) = 0; + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + Bx[i] = b (i,j); + + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, + X_CAST (const double *, Ax), + NULL, X_CAST (double *, Xx), + NULL, X_CAST (double *, Bx), + NULL, Numeric, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve solve failed"); + + umfpack_zi_report_status (control, status); + + err = -1; + + break; + } + + for (int i = 0; i < b_nr; i++) + { + Complex tmp = Xx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b, int& info, + double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return ComplexMatrix (); + } +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return SparseComplexMatrix (); + } +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return ComplexMatrix (); + } +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, + const SparseComplexMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return SparseComplexMatrix (); + } +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b) const +{ + int info; double rcond; + return solve (mattype, b, info, rcond); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ColumnVector& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix tmp (b); + return solve (mattype, tmp, info, rcond, sing_handler).column (0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, + const ComplexColumnVector& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix tmp (b); + return solve (mattype, tmp, info, rcond, sing_handler).column (0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const Matrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const Matrix& b, int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const Matrix& b, int& info, + double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseMatrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +ComplexMatrix +SparseComplexMatrix::solve (const ComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const ComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseComplexMatrix::solve (const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseComplexMatrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseComplexMatrix::solve (const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ColumnVector& b) const +{ + int info; double rcond; + return solve (b, info, rcond); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ColumnVector& b, int& info) const +{ + double rcond; + return solve (b, info, rcond); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ColumnVector& b, int& info, + double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix tmp (b); + return solve (tmp, info, rcond, sing_handler).column (0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ComplexColumnVector& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ComplexColumnVector& b, int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ComplexColumnVector& b, int& info, + double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseComplexMatrix::solve (const ComplexColumnVector& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix tmp (b); + return solve (tmp, info, rcond, sing_handler).column (0); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const Matrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const Matrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const Matrix& b, int& info, int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return ComplexMatrix (); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseMatrix& b, int& info, + int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return SparseComplexMatrix (); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const ComplexMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const ComplexMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseComplexMatrix::lssolve (const ComplexMatrix& b, int& info, + int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return ComplexMatrix (); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseComplexMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseComplexMatrix::lssolve (const SparseComplexMatrix& b, int& info, + int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return SparseComplexMatrix (); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ColumnVector& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ColumnVector& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ColumnVector& b, int& info, int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return ComplexColumnVector (); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ComplexColumnVector& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ComplexColumnVector& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseComplexMatrix::lssolve (const ComplexColumnVector& b, int& info, + int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseComplexMatrix::lssolve not implemented yet"); + return ComplexColumnVector (); +} + +// unary operations +SparseBoolMatrix +SparseComplexMatrix::operator ! (void) const +{ + int nr = rows (); + int nc = cols (); + int nz1 = nnz (); + int nz2 = nr*nc - nz1; + + SparseBoolMatrix r (nr, nc, nz2); + + int ii = 0; + int jj = 0; + r.cidx (0) = 0; + for (int i = 0; i < nc; i++) + { + for (int j = 0; j < nr; j++) + { + if (jj < cidx(i+1) && ridx(jj) == j) + jj++; + else + { + r.data(ii) = true; + r.ridx(ii++) = j; + } + } + r.cidx (i+1) = ii; + } + + return r; +} + +SparseComplexMatrix +SparseComplexMatrix::squeeze (void) const +{ + return MSparse::squeeze (); +} + +SparseComplexMatrix +SparseComplexMatrix::index (idx_vector& i, int resize_ok) const +{ + return MSparse::index (i, resize_ok); +} + +SparseComplexMatrix +SparseComplexMatrix::index (idx_vector& i, idx_vector& j, int resize_ok) const +{ + return MSparse::index (i, j, resize_ok); +} + +SparseComplexMatrix +SparseComplexMatrix::index (Array& ra_idx, int resize_ok) const +{ + return MSparse::index (ra_idx, resize_ok); +} +SparseComplexMatrix +SparseComplexMatrix::reshape (const dim_vector& new_dims) const +{ + return MSparse::reshape (new_dims); +} + +SparseComplexMatrix +SparseComplexMatrix::permute (const Array& vec, bool inv) const +{ + return MSparse::permute (vec, inv); +} + +SparseComplexMatrix +SparseComplexMatrix::ipermute (const Array& vec) const +{ + return MSparse::ipermute (vec); +} + +// other operations + +SparseComplexMatrix +SparseComplexMatrix::map (c_c_Mapper f) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + bool f_zero = (f(0.0) == 0.0); + + // Count number of non-zero elements + int nel = (f_zero ? 0 : nr*nc - nz); + for (int i = 0; i < nz; i++) + if (f (data(i)) != 0.0) + nel++; + + SparseComplexMatrix retval (nr, nc, nel); + + if (f_zero) + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + Complex tmp = f (elem (i, j)); + if (tmp != 0.0) + { + retval.data(ii) = tmp; + retval.ridx(ii++) = i; + } + } + retval.cidx(j+1) = ii; + } + } + else + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + retval.data(ii) = f (elem(i)); + retval.ridx(ii++) = ridx(i); + } + retval.cidx(j+1) = ii; + } + } + + return retval; +} + +SparseMatrix +SparseComplexMatrix::map (d_c_Mapper f) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + bool f_zero = (f(0.0) == 0.0); + + // Count number of non-zero elements + int nel = (f_zero ? 0 : nr*nc - nz); + for (int i = 0; i < nz; i++) + if (f (data(i)) != 0.0) + nel++; + + SparseMatrix retval (nr, nc, nel); + + if (f_zero) + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + double tmp = f (elem (i, j)); + if (tmp != 0.0) + { + retval.data(ii) = tmp; + retval.ridx(ii++) = i; + } + } + retval.cidx(j+1) = ii; + } + } + else + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + retval.data(ii) = f (elem(i)); + retval.ridx(ii++) = ridx(i); + } + retval.cidx(j+1) = ii; + } + } + + return retval; +} + +SparseBoolMatrix +SparseComplexMatrix::map (b_c_Mapper f) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + bool f_zero = f(0.0); + + // Count number of non-zero elements + int nel = (f_zero ? 0 : nr*nc - nz); + for (int i = 0; i < nz; i++) + if (f (data(i)) != 0.0) + nel++; + + SparseBoolMatrix retval (nr, nc, nel); + + if (f_zero) + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + bool tmp = f (elem (i, j)); + if (tmp) + { + retval.data(ii) = tmp; + retval.ridx(ii++) = i; + } + } + retval.cidx(j+1) = ii; + } + } + else + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + retval.data(ii) = f (elem(i)); + retval.ridx(ii++) = ridx(i); + } + retval.cidx(j+1) = ii; + } + } + + return retval; +} + +SparseComplexMatrix& +SparseComplexMatrix::apply (c_c_Mapper f) +{ + *this = map (f); + return *this; +} + +bool +SparseComplexMatrix::any_element_is_inf_or_nan (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + Complex val = data (i); + if (xisinf (val) || xisnan (val)) + return true; + } + + return false; +} + +// Return true if no elements have imaginary components. + +bool +SparseComplexMatrix::all_elements_are_real (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + double ip = imag (data (i)); + + if (ip != 0.0 || lo_ieee_signbit (ip)) + return false; + } + + return true; +} + +// Return nonzero if any element of CM has a non-integer real or +// imaginary part. Also extract the largest and smallest (real or +// imaginary) values and return them in MAX_VAL and MIN_VAL. + +bool +SparseComplexMatrix::all_integers (double& max_val, double& min_val) const +{ + int nel = nnz (); + + if (nel == 0) + return false; + + max_val = real(data (0)); + min_val = real(data (0)); + + for (int i = 0; i < nel; i++) + { + Complex val = data (i); + + double r_val = real (val); + double i_val = imag (val); + + if (r_val > max_val) + max_val = r_val; + + if (i_val > max_val) + max_val = i_val; + + if (r_val < min_val) + min_val = r_val; + + if (i_val < min_val) + min_val = i_val; + + if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val) + return false; + } + + return true; +} + +bool +SparseComplexMatrix::too_large_for_float (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + Complex val = data (i); + + double r_val = real (val); + double i_val = imag (val); + + if (r_val > FLT_MAX + || i_val > FLT_MAX + || r_val < FLT_MIN + || i_val < FLT_MIN) + return true; + } + + return false; +} + +// XXX FIXME XXX Do these really belong here? Maybe they should be +// in a base class? + +SparseBoolMatrix +SparseComplexMatrix::all (int dim) const +{ + SPARSE_ALL_OP (dim); +} + +SparseBoolMatrix +SparseComplexMatrix::any (int dim) const +{ + SPARSE_ANY_OP (dim); +} + +SparseComplexMatrix +SparseComplexMatrix::cumprod (int dim) const +{ + SPARSE_CUMPROD (SparseComplexMatrix, Complex, cumprod); +} + +SparseComplexMatrix +SparseComplexMatrix::cumsum (int dim) const +{ + SPARSE_CUMSUM (SparseComplexMatrix, Complex, cumsum); +} + +SparseComplexMatrix +SparseComplexMatrix::prod (int dim) const +{ + SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, *=, 1.0, 1.0); +} + +SparseComplexMatrix +SparseComplexMatrix::sum (int dim) const +{ + SPARSE_REDUCTION_OP (SparseComplexMatrix, Complex, +=, 0.0, 0.0); +} + +SparseComplexMatrix +SparseComplexMatrix::sumsq (int dim) const +{ +#define ROW_EXPR \ + Complex d = elem (i, j); \ + tmp [i] += d * conj (d) + +#define COL_EXPR \ + Complex d = elem (i, j); \ + tmp [j] += d * conj (d) + + SPARSE_BASE_REDUCTION_OP (SparseComplexMatrix, Complex, ROW_EXPR, + COL_EXPR, 0.0, 0.0); + +#undef ROW_EXPR +#undef COL_EXPR +} + +SparseMatrix SparseComplexMatrix::abs (void) const +{ + int nz = nnz (); + int nc = cols (); + + SparseMatrix retval (rows(), nc, nz); + + for (int i = 0; i < nc + 1; i++) + retval.cidx (i) = cidx (i); + + for (int i = 0; i < nz; i++) + { + retval.data (i) = ::abs (data (i)); + retval.ridx (i) = ridx (i); + } + + return retval; +} + +SparseComplexMatrix +SparseComplexMatrix::diag (int k) const +{ + int nnr = rows (); + int nnc = cols (); + + if (k > 0) + nnc -= k; + else if (k < 0) + nnr += k; + + SparseComplexMatrix d; + + if (nnr > 0 && nnc > 0) + { + int ndiag = (nnr < nnc) ? nnr : nnc; + + // Count the number of non-zero elements + int nel = 0; + if (k > 0) + { + for (int i = 0; i < ndiag; i++) + if (elem (i, i+k) != 0.) + nel++; + } + else if ( k < 0) + { + for (int i = 0; i < ndiag; i++) + if (elem (i-k, i) != 0.) + nel++; + } + else + { + for (int i = 0; i < ndiag; i++) + if (elem (i, i) != 0.) + nel++; + } + + d = SparseComplexMatrix (ndiag, 1, nel); + d.xcidx (0) = 0; + d.xcidx (1) = nel; + + int ii = 0; + if (k > 0) + { + for (int i = 0; i < ndiag; i++) + { + Complex tmp = elem (i, i+k); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else if ( k < 0) + { + for (int i = 0; i < ndiag; i++) + { + Complex tmp = elem (i-k, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else + { + for (int i = 0; i < ndiag; i++) + { + Complex tmp = elem (i, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + } + else + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); + + return d; +} + +std::ostream& +operator << (std::ostream& os, const SparseComplexMatrix& a) +{ + int nc = a.cols (); + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int j = 0; j < nc; j++) { + OCTAVE_QUIT; + for (int i = a.cidx(j); i < a.cidx(j+1); i++) { + os << a.ridx(i) + 1 << " " << j + 1 << " "; + octave_write_complex (os, a.data(i)); + os << "\n"; + } + } + + return os; +} + +std::istream& +operator >> (std::istream& is, SparseComplexMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + + if (nr < 1 || nc < 1) + is.clear (std::ios::badbit); + else + { + int itmp, jtmp, jold = 0; + Complex tmp; + int ii = 0; + + a.cidx (0) = 0; + for (int i = 0; i < nz; i++) + { + is >> itmp; + itmp--; + is >> jtmp; + jtmp--; + tmp = octave_read_complex (is); + + if (is) + { + if (jold != jtmp) + { + for (int j = jold; j < jtmp; j++) + a.cidx(j+1) = ii; + + jold = jtmp; + } + a.data (ii) = tmp; + a.ridx (ii++) = itmp; + } + else + goto done; + } + + for (int j = jold; j < nc; j++) + a.cidx(j+1) = ii; + } + + done: + + return is; +} + +SparseComplexMatrix +operator * (const SparseComplexMatrix& m, const SparseMatrix& a) +{ + SparseComplexMatrix tmp (a); + return m * tmp; +} + +SparseComplexMatrix +operator * (const SparseMatrix& m, const SparseComplexMatrix& a) +{ + SparseComplexMatrix tmp (m); + return tmp * a; +} + +SparseComplexMatrix +operator * (const SparseComplexMatrix& m, const SparseComplexMatrix& a) +{ +#ifdef HAVE_SPARSE_BLAS + // XXX FIXME XXX Isn't there a sparse BLAS ?? +#else + // Use Andy's sparse matrix multiply function + SPARSE_SPARSE_MUL (SparseComplexMatrix, Complex); +#endif +} + +// XXX FIXME XXX -- it would be nice to share code among the min/max +// functions below. + +#define EMPTY_RETURN_CHECK(T) \ + if (nr == 0 || nc == 0) \ + return T (nr, nc); + +SparseComplexMatrix +min (const Complex& c, const SparseComplexMatrix& m) +{ + SparseComplexMatrix result; + + int nr = m.rows (); + int nc = m.columns (); + + EMPTY_RETURN_CHECK (SparseComplexMatrix); + + if (abs(c) == 0.) + return SparseComplexMatrix (nr, nc); + else + { + result = SparseComplexMatrix (m); + + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + result.data(i) = xmin(c, m.data(i)); + } + + return result; +} + +SparseComplexMatrix +min (const SparseComplexMatrix& m, const Complex& c) +{ + return min (c, m); +} + +SparseComplexMatrix +min (const SparseComplexMatrix& a, const SparseComplexMatrix& b) +{ + SparseComplexMatrix r; + + if ((a.rows() == b.rows()) && (a.cols() == b.cols())) + { + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) + return SparseComplexMatrix (a_nr, a_nc); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + else + { + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + r.cidx (0) = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + Complex tmp = xmin (a.data(ja), 0.); + if (tmp != 0.) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = tmp; + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + Complex tmp = xmin (0., b.data(jb)); + if (tmp != 0.) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = tmp; + jx++; + } + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmin (a.data(ja), b.data(jb)); + if (tmp != 0.) + { + r.data(jx) = tmp; + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + r.maybe_compress (); + } + } + else + (*current_liboctave_error_handler) ("matrix size mismatch"); + + return r; +} + +SparseComplexMatrix +max (const Complex& c, const SparseComplexMatrix& m) +{ + SparseComplexMatrix result; + + int nr = m.rows (); + int nc = m.columns (); + + EMPTY_RETURN_CHECK (SparseComplexMatrix); + + // Count the number of non-zero elements + if (xmax(c, 0.) != 0.) + { + result = SparseComplexMatrix (nr, nc, c); + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + result.xdata(m.ridx(i) + j * nr) = xmax (c, m.data(i)); + } + else + result = SparseComplexMatrix (m); + + return result; +} + +SparseComplexMatrix +max (const SparseComplexMatrix& m, const Complex& c) +{ + return max (c, m); +} + +SparseComplexMatrix +max (const SparseComplexMatrix& a, const SparseComplexMatrix& b) +{ + SparseComplexMatrix r; + + if ((a.rows() == b.rows()) && (a.cols() == b.cols())) + { + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr == 0 || b_nc == 0) + return SparseComplexMatrix (a_nr, a_nc); + if (a.nnz () == 0) + return SparseComplexMatrix (b); + if (b.nnz () == 0) + return SparseComplexMatrix (a); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + else + { + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + r.cidx (0) = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + Complex tmp = xmax (a.data(ja), 0.); + if (tmp != 0.) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = tmp; + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + Complex tmp = xmax (0., b.data(jb)); + if (tmp != 0.) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = tmp; + jx++; + } + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmax (a.data(ja), b.data(jb)); + if (tmp != 0.) + { + r.data(jx) = tmp; + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + r.maybe_compress (); + } + } + else + (*current_liboctave_error_handler) ("matrix size mismatch"); + + return r; +} + +SPARSE_SMS_CMP_OPS (SparseComplexMatrix, 0.0, real, Complex, + 0.0, real) +SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex, 0.0) + +SPARSE_SSM_CMP_OPS (Complex, 0.0, real, SparseComplexMatrix, + 0.0, real) +SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix, 0.0) + +SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, 0.0, real, SparseComplexMatrix, + 0.0, real) +SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix, 0.0) + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/CSparse.h b/liboctave/CSparse.h new file mode 100644 --- /dev/null +++ b/liboctave/CSparse.h @@ -0,0 +1,431 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_CSparse_h) +#define octave_CSparse_h 1 + +#include "dMatrix.h" +#include "dNDArray.h" +#include "CNDArray.h" +#include "dColVector.h" +#include "CColVector.h" +#include "oct-cmplx.h" + +#include "CmplxDET.h" +#include "MSparse.h" +#include "MSparse-defs.h" +#include "Sparse-op-defs.h" +#include "SparseType.h" + +class SparseMatrix; +class SparseBoolMatrix; + +class +SparseComplexMatrix : public MSparse +{ +public: + + typedef void (*solve_singularity_handler) (double rcond); + + SparseComplexMatrix (void) : MSparse () { } + + SparseComplexMatrix (int r, int c) : MSparse (r, c) { } + + explicit SparseComplexMatrix (int r, int c, Complex val) + : MSparse (r, c, val) { } + + SparseComplexMatrix (int r, int c, double val) + : MSparse (r, c, Complex (val)) { } + + SparseComplexMatrix (const SparseComplexMatrix& a) + : MSparse (a) { } + + SparseComplexMatrix (const SparseComplexMatrix& a, const dim_vector& dv) + : MSparse (a, dv) { } + + SparseComplexMatrix (const MSparse& a) : MSparse (a) { } + + explicit SparseComplexMatrix (const ComplexMatrix& a) + : MSparse (a) { } + + explicit SparseComplexMatrix (const ComplexNDArray& a) + : MSparse (a) { } + + explicit SparseComplexMatrix (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : MSparse (a, r, c, nr, nc, sum_terms) { } + + explicit SparseComplexMatrix (const Array a, + const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : MSparse (a, r, c, nr, nc, sum_terms) { } + + explicit SparseComplexMatrix (const SparseMatrix& a); + + explicit SparseComplexMatrix (const SparseBoolMatrix& a); + + SparseComplexMatrix (int r, int c, int num_nz) + : MSparse (r, c, num_nz) { } + + SparseComplexMatrix& operator = (const SparseComplexMatrix& a) + { + MSparse::operator = (a); + return *this; + } + + bool operator == (const SparseComplexMatrix& a) const; + bool operator != (const SparseComplexMatrix& a) const; + + bool is_hermitian (void) const; + + SparseComplexMatrix max (int dim = 0) const; + SparseComplexMatrix max (Array2& index, int dim = 0) const; + SparseComplexMatrix min (int dim = 0) const; + SparseComplexMatrix min (Array2& index, int dim = 0) const; + + SparseComplexMatrix& insert (const SparseComplexMatrix& a, int r, int c); + SparseComplexMatrix& insert (const SparseMatrix& a, int r, int c); + + SparseComplexMatrix concat (const SparseComplexMatrix& rb, + const Array& ra_idx); + SparseComplexMatrix concat (const SparseMatrix& rb, + const Array& ra_idx); + + ComplexMatrix matrix_value (void) const; + + SparseComplexMatrix hermitian (void) const; // complex conjugate transpose + SparseComplexMatrix transpose (void) const + { return MSparse::transpose (); } + + friend SparseComplexMatrix conj (const SparseComplexMatrix& a); + + SparseComplexMatrix inverse (void) const; + SparseComplexMatrix inverse (int& info) const; + SparseComplexMatrix inverse (int& info, double& rcond, int force = 0, + int calc_cond = 1) const; + + ComplexDET determinant (void) const; + ComplexDET determinant (int& info) const; + ComplexDET determinant (int& info, double& rcond, + int calc_cond = 1) const; + +private: + // Diagonal matrix solvers + ComplexMatrix dsolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix dsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix dsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Upper triangular matrix solvers + ComplexMatrix utsolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix utsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix utsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Lower triangular matrix solvers + ComplexMatrix ltsolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix ltsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix ltsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Tridiagonal matrix solvers + ComplexMatrix trisolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix trisolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix trisolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Banded matrix solvers (umfpack/cholesky) + ComplexMatrix bsolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix bsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix bsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Full matrix solvers (umfpack/cholesky) + void * factorize (int& err, double &rcond, Matrix &Control, Matrix &Info, + solve_singularity_handler sing_handler) const; + + ComplexMatrix fsolve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix fsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix fsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + +public: + // Generic interface to solver with no probing of type + ComplexMatrix solve (SparseType &typ, const Matrix& b) const; + ComplexMatrix solve (SparseType &typ, const Matrix& b, int& info) const; + ComplexMatrix solve (SparseType &typ, const Matrix& b, int& info, + double& rcond) const; + ComplexMatrix solve (SparseType &typ, const Matrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, + int& info) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (SparseType &typ, const SparseMatrix& b) const; + SparseComplexMatrix solve (SparseType &typ, const SparseMatrix& b, + int& info) const; + SparseComplexMatrix solve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond) const; + SparseComplexMatrix solve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (SparseType &typ, + const SparseComplexMatrix& b) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, + int& info) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (SparseType &typ, const ColumnVector& b) const; + ComplexColumnVector solve (SparseType &typ, const ColumnVector& b, + int& info) const; + ComplexColumnVector solve (SparseType &typ, const ColumnVector& b, + int& info, double& rcond) const; + ComplexColumnVector solve (SparseType &typ, const ColumnVector& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (SparseType &typ, + const ComplexColumnVector& b) const; + ComplexColumnVector solve (SparseType &typ, + const ComplexColumnVector& b, int& info) const; + ComplexColumnVector solve (SparseType &typ, const ComplexColumnVector& b, + int& info, double& rcond) const; + ComplexColumnVector solve (SparseType &typ, const ComplexColumnVector& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Generic interface to solver with probing of type + ComplexMatrix solve (const Matrix& b) const; + ComplexMatrix solve (const Matrix& b, int& info) const; + ComplexMatrix solve (const Matrix& b, int& info, double& rcond) const; + ComplexMatrix solve (const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix solve (const ComplexMatrix& b) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info, + double& rcond) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (const SparseMatrix& b) const; + SparseComplexMatrix solve (const SparseMatrix& b, int& info) const; + SparseComplexMatrix solve (const SparseMatrix& b, int& info, + double& rcond) const; + SparseComplexMatrix solve (const SparseMatrix& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (const SparseComplexMatrix& b) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info, + double& rcond) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (const ColumnVector& b) const; + ComplexColumnVector solve (const ColumnVector& b, int& info) const; + ComplexColumnVector solve (const ColumnVector& b, int& info, + double& rcond) const; + ComplexColumnVector solve (const ColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (const ComplexColumnVector& b) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info, + double& rcond) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix lssolve (const Matrix& b) const; + ComplexMatrix lssolve (const Matrix& b, int& info) const; + ComplexMatrix lssolve (const Matrix& b, int& info, int& rank) const; + + ComplexMatrix lssolve (const ComplexMatrix& b) const; + ComplexMatrix lssolve (const ComplexMatrix& b, int& info) const; + ComplexMatrix lssolve (const ComplexMatrix& b, int& info, + int& rank) const; + + SparseComplexMatrix lssolve (const SparseMatrix& b) const; + SparseComplexMatrix lssolve (const SparseMatrix& b, int& info) const; + SparseComplexMatrix lssolve (const SparseMatrix& b, int& info, + int& rank) const; + + SparseComplexMatrix lssolve (const SparseComplexMatrix& b) const; + SparseComplexMatrix lssolve (const SparseComplexMatrix& b, + int& info) const; + SparseComplexMatrix lssolve (const SparseComplexMatrix& b, int& info, + int& rank) const; + + ComplexColumnVector lssolve (const ColumnVector& b) const; + ComplexColumnVector lssolve (const ColumnVector& b, int& info) const; + ComplexColumnVector lssolve (const ColumnVector& b, int& info, + int& rank) const; + + ComplexColumnVector lssolve (const ComplexColumnVector& b) const; + ComplexColumnVector lssolve (const ComplexColumnVector& b, int& info) const; + ComplexColumnVector lssolve (const ComplexColumnVector& b, int& info, + int& rank) const; + + SparseComplexMatrix squeeze (void) const; + + SparseComplexMatrix index (idx_vector& i, int resize_ok) const; + + SparseComplexMatrix index (idx_vector& i, idx_vector& j, int resize_ok) const; + + SparseComplexMatrix index (Array& ra_idx, int resize_ok) const; + + SparseComplexMatrix reshape (const dim_vector& new_dims) const; + + SparseComplexMatrix permute (const Array& vec, bool inv = false) const; + + SparseComplexMatrix ipermute (const Array& vec) const; + + SparseComplexMatrix map (c_c_Mapper f) const; + SparseMatrix map (d_c_Mapper f) const; + SparseBoolMatrix map (b_c_Mapper f) const; + + SparseComplexMatrix& apply (c_c_Mapper f); + + bool any_element_is_inf_or_nan (void) const; + bool all_elements_are_real (void) const; + bool all_integers (double& max_val, double& min_val) const; + bool too_large_for_float (void) const; + + SparseBoolMatrix operator ! (void) const; + + SparseBoolMatrix all (int dim = -1) const; + SparseBoolMatrix any (int dim = -1) const; + + SparseComplexMatrix cumprod (int dim = -1) const; + SparseComplexMatrix cumsum (int dim = -1) const; + SparseComplexMatrix prod (int dim = -1) const; + SparseComplexMatrix sum (int dim = -1) const; + SparseComplexMatrix sumsq (int dim = -1) const; + SparseMatrix abs (void) const; + + SparseComplexMatrix diag (int k = 0) const; + + // i/o + friend std::ostream& operator << (std::ostream& os, + const SparseComplexMatrix& a); + friend std::istream& operator >> (std::istream& is, + SparseComplexMatrix& a); +}; + +extern SparseComplexMatrix operator * (const SparseMatrix&, + const SparseComplexMatrix&); +extern SparseComplexMatrix operator * (const SparseComplexMatrix&, + const SparseMatrix&); +extern SparseComplexMatrix operator * (const SparseComplexMatrix&, + const SparseComplexMatrix&); + +extern SparseComplexMatrix min (const Complex& c, + const SparseComplexMatrix& m); +extern SparseComplexMatrix min (const SparseComplexMatrix& m, + const Complex& c); +extern SparseComplexMatrix min (const SparseComplexMatrix& a, + const SparseComplexMatrix& b); + +extern SparseComplexMatrix max (const Complex& c, + const SparseComplexMatrix& m); +extern SparseComplexMatrix max (const SparseComplexMatrix& m, + const Complex& c); +extern SparseComplexMatrix max (const SparseComplexMatrix& a, + const SparseComplexMatrix& b); + +SPARSE_SMS_CMP_OP_DECLS (SparseComplexMatrix, Complex) +SPARSE_SMS_BOOL_OP_DECLS (SparseComplexMatrix, Complex) + +SPARSE_SSM_CMP_OP_DECLS (Complex, SparseComplexMatrix) +SPARSE_SSM_BOOL_OP_DECLS (Complex, SparseComplexMatrix) + +SPARSE_SMSM_CMP_OP_DECLS (SparseComplexMatrix, SparseComplexMatrix) +SPARSE_SMSM_BOOL_OP_DECLS (SparseComplexMatrix, SparseComplexMatrix) + +SPARSE_FORWARD_DEFS (MSparse, SparseComplexMatrix, ComplexMatrix, Complex) + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,219 @@ +2005-02-25 John W. Eaton + + Sparse merge. + + 2005-02-13 David Bateman + + * CSparse.cc (SparseComplexMatrix:dsolve, SparseComplexMatrix:utsolve, + SparseComplexMatrix::ltsolve, SparseComplexMatrix::trisolve, + SparseComplexMatrix::bsolve, SparseComplexMatrix:fsolve): Split sparse + solver into separate functions for the diagonal, upper, lower + triangular, tridiagonal, banded and full cases. + (SparseComplexMatrix::solve): rewrite to call the above function. One + version that probes the matrix type and another that assumes the type + is passed. + + * dSparse.cc (SparseMatrix:dsolve, SparseMatrix:utsolve, + SparseMatrix::ltsolve, SparseMatrix::trisolve, + SparseMatrix::bsolve, SparseMatrix:fsolve): Likewise + (SparseMatrix::solve): Likewise + + * CSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve, fsolve): + Declaration of new functions + * dSparse.h (dsolve, utsolve, ltsolve, trisolve, bsolve, fsolve): + Likewise + + * CSparse.cc (operator !): Reverse the sense of the test. + * dSpase.cc (operator !): Likewise + + * dSparse.h (type, band_size, is_dense, triangular_row_perm, + triangular_col_perm, sparse_info): Remove matrix type code + * CSparse.h (type, band_size, is_dense, triangular_row_perm, + triangular_col_perm, sparse_info): Likewise + * boolSparse.h (type, band_size, is_dense, triangular_row_perm, + triangular_col_perm, sparse_info): Likewise + * MSparse.h (type, band_size, is_dense, triangular_row_perm, + triangular_col_perm, sparse_info): Likewise + * Sparse.h (type, band_size, is_dense, triangular_row_perm, + triangular_col_perm, sparse_info, matrix_type): Likewise + + * Sparse.cc (type, sparse_info, band_size): Remove type code + + * SparseType.h: New class for the matrix type used in solvers + * SparseType.cc: methods of sparse matrix type class + + * Makefile.in: Add SparseType.cc + + 2005-02-01 David Bateman + + * UMFPACK: Update to version 4.4 + * UMFPACK.patch: Version 4.4 contains most of the previous patch. Only + keep octave specific test files + + 2005-01-23 David Bateman + + * dSparse.cc (SparseMatrix::solve): Include tridiagonal, cholesky + tridiagonal and banded cholesky solvers. Remove calculation of + condition number for banded solvers. + * CSparse.cc (SparseComplexMatrix::solve): ditto. + + * Sparse.h (int type (int) const, bool is_dense (void) const): + new functions. + * MSparse.h (int type (int) const, bool is_dense (void) const): ditto + * dSparse.h (int type (int) const, bool is_dense (void) const): ditto + * CSparse.h (int type (int) const, bool is_dense (void) const): ditto + * boolSparse.h (int type (int) const, bool is_dense (void) const): + ditto + + * Sparse.cc (int Sparse::type (int) const, + bool Sparse::is_dense (void) const): New functions definition + + * Sparse.h (matrix_type typ): Move caching of matrix type to SparseRep, + so it actually is cached, but disable + + * oct-spparms.cc (SparseParams::init_keys): Change spmoni to spumoni + for compatiability + + 2005-01-18 David Bateman + + * Array.cc (Array::insert (const Array&, const Array&)): + Modify calculation of number elements to skip between copied blocks. + + 2005-01-07 David Bateman + + * Sparse.h : Reverse definitions of numel and nelem. + * Sparse.cc (assign1): Use numel and not nelem + * Sparse-op-def.h: Replace all uses of nelem with numel + + 2005-01-07 David Bateman + + * dbleDET.h: Make SparseMatrix a friend of the class DET + * CmplexDET.h: Make SparseComplexMatrix a friend of the class + ComplexDET + * dSparse.cc (SparseMatrix::determinant): Replace use of SparseDET + by DET + * dSparse.h (determinant): ditto + * CSparse.cc (SparseComplexMatrix::determinant): Replace use of + SparseComplexDET by ComplexDET + * CSparse.h (determinant): ditto + * SparsedbleDET.h, SparsedbleDET.cc, SparseCmplxDET.h, + SparseCmplxDET.cc: delete files + * Makefile.in: Delete reference to SparsedbleDET.h, SparsedbleDET.cc, + SparseCmplxDET.h andSparseCmplxDET.cc. + + * CSparse.cc (SparseComplexMatrix::solve): Store matrix type in + local variable to avoid variable shadowing. + * dSparse.cc (SparseMatrix::solve): ditto. + + * boolSparse.cc boolSparse.h CSparse.cc CSparse.h dSparse.cc + dSparse.h MSparse.cc MSparse-C.cc MSparse-d.cc MSparse-defs.h + MSparse.h oct-spparms.cc oct-spparms.h Sparse-b.cc Sparse.cc + Sparse-C.cc SparseCmplxLU.cc SparseCmplxLU.h SparsedbleLU.cc + SparsedbleLU.h Sparse-d.cc Sparse.h Sparse-op-defs.h sparse-sort.cc + sparse-sort.h: Remove additional licensing clause with authors + permission. + + 2004-12-30 John W. Eaton + + * MSparse.cc (SPARSE_A2S_OP_2, SPARSE_SA2_OP_2): + Loop counter is int, not size_t. + + * oct-spparms.cc (SparseParams::operator =): Return *this. + + * Sparse-op-defs.h (SPARSE_SPARSE_MUL): Delete unused variable tmpval. + + * dSparse.cc (operator << (ostream&, const SparseMatrix&), atan2): + Delete unused variables. + (SparseMatrix::solve): Avoid warnings about uninitialized + variables and variables that might be clobbered by longjmp. + + * CSparse.cc (operator << (ostream&, const SparseComplexMatrix&), + min, max): Delete unused variables. + (SparseComplexMatrix::solve): Avoid warnings about uninitialized + variables and variables that might be clobbered by longjmp. + + * Makefile.in (UMFPACK_SPECIAL): Include .d files in the list. + + * Sparse-op-defs.h (SPARSE_SMS_BIN_OP_2, SPARSE_SSM_BIN_OP_2): + Loop counter is int, not size_t. + + * CSparse.cc (SparseComplexMatrix::hermitian): Avoid shadow warnings. + * Sparse.cc (Sparse::Sparse, Sparse::type, assign): Likewise. + + * Sparse.h (Sparse::SparseRep): Order data members and initializer + lists consistently. + + * mx-base.h: Include boolSparse.h, dSparse.h, and CSparse.h. + + 2004-12-29 John W. Eaton + + * COLAMD.files (COLAMD_EXTRAS): New variable. + * UMFPACK.files (UMFPACK_EXTRAS): New variable. + * Makefile.in (DISTFILES): Add $(COLAMD_EXTRAS) and + $(UMFPACK_EXTRAS) to the list. + (DISTDIRS): New variable. + (dist): Handle $(DISTDIRS). + + Merge of sparse code from David Bateman and + Andy Adler . + + * Makefile.in (VPATH): ADD @srcdir@/COLAMD to the list. + + * Makefile.in (MAKEDEPS): Include $(COLAMD_SRC) and $(UMFPACK_SRC) + without directory prefix. + + * Makefile.in (LIBOCTAVE_OBJECTS): Add $(COLAMD_OBJ) and + $(UMFPACK_OBJ) to the list. + + * COLAMD: New directory. + * COLAMD.files: New file. + * Makefile.in: Include COLAMD.files. + (SOURCES): Add $(COLAMD_SOURCES) to the list. + (LIBOCTAVE_OBJECTS): Add $(COLAMD_OBJECTS) to the list. + (INCLUDES): Add $(COLAMD_INCLUDES) to the list. + + * UMFPACK: New directory. + * UMFPACK.patch, UMFPACK.README, UMFPACK.files, UMFPACK.rules: + New files. + * Makefile.in: Include UMFPACK.files and UMFPACK.rules. + (SOURCES): Add $(UMFPACK_SOURCES) to the list. + (LIBOCTAVE_OBJECTS): Add $(UMFPACK_OBJECTS) to the list. + (INCLUDES): Add $(UMFPACK_INCLUDES) to the list. + + * Makefile.in (SPARSE_MX_OP_INC): New variable. + (INCLUDES): Add it to the list. + (SPARSE_MX_OP_SRC): New variable. + (LIBOCTAVE_CXX_SOURCES): Add it to the list. + (distclean): Remove $(SPARSE_MX_OP_INC) and $(SPARSE_MX_OP_SRC). + (stamp-prereq): Depend on $(SPARSE_MX_OP_INC) and $(SPARSE_MX_OP_SRC). + + * sparse-mk-ops.awk, sparse-mx-ops: New files. + * Makefile.in (DISTFILES): Add them to the lists. + + * oct-spparms.h, sparse-sort.h: New files. + * Makefile.in (INCLUDES): Add them to the list. + + * oct-spparms.cc, sparse-sort.cc: New files. + * Makefile.in (LIBOCTAVE_CXX_SOURCES): Add them to the list. + + * sparse-base-lu.cc: New file. + * Makefile.in (TEMPLATE_SRC): Add it to the list. + + * boolSparse.cc, CSparse.cc, dSparse.cc, MSparse.cc, Sparse.cc, + SparseCmplxDET.cc, SparseCmplxLU.cc, SparsedbleDET.cc, + SparsedbleLU.cc: New files. + * Makefile.in (MATRIX_SRC): Add them to the list. + + * boolSparse.h, CSparse.h, dSparse.h, MSparse-defs.h, MSparse.h, + Sparse.h, oct-spparms.h, sparse-base-lu.h, SparseCmplxDET.h, + SparseCmplxLU.h, SparsedbleDET.h, SparsedbleLU.h, + Sparse-op-defs.h: New files. + * Makefile.in (MATRIX_INC): Add them to the appropriate lists. + + * MSparse-d.cc, MSparse-C.cc, Sparse-b.cc, Sparse-d.cc, + Sparse-C.cc: New files. + * Makefile.in (TI_SRC): Add them to the list. + 2005-02-18 John W. Eaton * file-ops.cc (file_ops::canonicalize_file_name) [HAVE_RESOLVEPATH]: diff --git a/liboctave/CmplxDET.h b/liboctave/CmplxDET.h --- a/liboctave/CmplxDET.h +++ b/liboctave/CmplxDET.h @@ -31,6 +31,7 @@ ComplexDET { friend class ComplexMatrix; +friend class SparseComplexMatrix; public: diff --git a/liboctave/MSparse-C.cc b/liboctave/MSparse-C.cc new file mode 100644 --- /dev/null +++ b/liboctave/MSparse-C.cc @@ -0,0 +1,39 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "oct-cmplx.h" + +#include "MSparse.h" +#include "MSparse.cc" + +template class MSparse; + +INSTANTIATE_SPARSE_FRIENDS (Complex); + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/MSparse-d.cc b/liboctave/MSparse-d.cc new file mode 100644 --- /dev/null +++ b/liboctave/MSparse-d.cc @@ -0,0 +1,37 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MSparse.h" +#include "MSparse.cc" + +template class MSparse; + +INSTANTIATE_SPARSE_FRIENDS (double); + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/MSparse-defs.h b/liboctave/MSparse-defs.h new file mode 100644 --- /dev/null +++ b/liboctave/MSparse-defs.h @@ -0,0 +1,217 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_MSparse_defs_h) +#define octave_MSparse_defs_h 1 + +// Nothing like a little CPP abuse to brighten everyone's day. + +// A macro that can be used to declare and instantiate OP= operators. +#define SPARSE_OP_ASSIGN_DECL(A_T, E_T, OP, PFX, LTGT, RHS_T) \ + PFX A_T& \ + operator OP LTGT (A_T&, const RHS_T&) + +// All the OP= operators that we care about. +#define SPARSE_OP_ASSIGN_DECLS(A_T, E_T, PFX, LTGT, RHS_T) \ + SPARSE_OP_ASSIGN_DECL (A_T, E_T, +=, PFX, LTGT, RHS_T); \ + SPARSE_OP_ASSIGN_DECL (A_T, E_T, -=, PFX, LTGT, RHS_T); + +// Generate forward declarations for OP= operators. +#define SPARSE_OP_ASSIGN_FWD_DECLS(A_T, RHS_T) \ + SPARSE_OP_ASSIGN_DECLS (A_T, T, template , , RHS_T) + +// Generate friend declarations for the OP= operators. +#define SPARSE_OP_ASSIGN_FRIENDS(A_T, RHS_T) \ + SPARSE_OP_ASSIGN_DECLS (A_T, T, friend, <>, RHS_T) + +// Instantiate the OP= operators. +#define SPARSE_OP_ASSIGN_DEFS(A_T, E_T, RHS_T) \ + SPARSE_OP_ASSIGN_DECLS (A_T, E_T, template, , RHS_T) + +// A function that can be used to forward OP= operations from derived +// classes back to us. +#define SPARSE_OP_ASSIGN_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T) \ + inline R \ + F (X_T& x, const Y_T& y) \ + { \ + return R (F (C_X (x), C_Y (y))); \ + } + +// All the OP= operators that we care about forwarding. +#define SPARSE_OP_ASSIGN_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_OP_ASSIGN_FWD_FCN (R, operator +=, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_OP_ASSIGN_FWD_FCN (R, operator -=, T, C_X, X_T, C_Y, Y_T) + +// A macro that can be used to declare and instantiate unary operators. +#define SPARSE_UNOP(A_T, E_T, F, PFX, LTGT) \ + PFX A_T \ + F LTGT (const A_T&) + +// All the unary operators that we care about. +#define SPARSE_UNOP_DECLS(A_T, E_T, PFX, LTGT) \ + SPARSE_UNOP (A_T, E_T, operator +, PFX, LTGT); \ + SPARSE_UNOP (A_T, E_T, operator -, PFX, LTGT); + +// Generate forward declarations for unary operators. +#define SPARSE_UNOP_FWD_DECLS(A_T) \ + SPARSE_UNOP_DECLS (A_T, T, template , ) + +// Generate friend declarations for the unary operators. +#define SPARSE_UNOP_FRIENDS(A_T) \ + SPARSE_UNOP_DECLS (A_T, T, friend, <>) + +// Instantiate the unary operators. +#define SPARSE_UNOP_DEFS(A_T, E_T) \ + SPARSE_UNOP_DECLS (A_T, E_T, template, ) + +// A function that can be used to forward unary operations from derived +// classes back to us. +#define SPARSE_UNOP_FWD_FCN(R, F, T, C_X, X_T) \ + inline R \ + F (const X_T& x) \ + { \ + return R (F (C_X (x))); \ + } + +// All the unary operators that we care about forwarding. +#define SPARSE_UNOP_FWD_DEFS(R, T, C_X, X_T) \ + SPARSE_UNOP_FWD_FCN (R, operator +, T, C_X, X_T) \ + SPARSE_UNOP_FWD_FCN (R, operator -, T, C_X, X_T) + +// A macro that can be used to declare and instantiate binary operators. +#define SPARSE_BINOP_DECL(A_T, E_T, F, PFX, LTGT, X_T, Y_T) \ + PFX A_T \ + F LTGT (const X_T&, const Y_T&) + +// All the binary operators that we care about. We have two +// sets of macros since the MArray OP MArray operations use functions +// (product and quotient) instead of operators (*, /). +#define SPARSE_BINOP_DECLS(A_T, F_T, E_T, PFX, LTGT, X_T, Y_T) \ + SPARSE_BINOP_DECL (F_T, E_T, operator +, PFX, LTGT, X_T, Y_T); \ + SPARSE_BINOP_DECL (F_T, E_T, operator -, PFX, LTGT, X_T, Y_T); \ + SPARSE_BINOP_DECL (A_T, E_T, operator *, PFX, LTGT, X_T, Y_T); \ + SPARSE_BINOP_DECL (A_T, E_T, operator /, PFX, LTGT, X_T, Y_T); + +#define SPARSE_AA_BINOP_DECLS(A_T, E_T, PFX, LTGT) \ + SPARSE_BINOP_DECL (A_T, E_T, operator +, PFX, LTGT, A_T, A_T); \ + SPARSE_BINOP_DECL (A_T, E_T, operator -, PFX, LTGT, A_T, A_T); \ + SPARSE_BINOP_DECL (A_T, E_T, quotient, PFX, LTGT, A_T, A_T); \ + SPARSE_BINOP_DECL (A_T, E_T, product, PFX, LTGT, A_T, A_T); + +// Generate forward declarations for binary operators. +#define SPARSE_BINOP_FWD_DECLS(A_T, F_T) \ + SPARSE_BINOP_DECLS (A_T, F_T, T, template , , A_T, T) \ + SPARSE_BINOP_DECLS (A_T, F_T, T, template , , T, A_T) \ + SPARSE_AA_BINOP_DECLS (A_T, T, template , ) + +// Generate friend declarations for the binary operators. +#define SPARSE_BINOP_FRIENDS(A_T, F_T) \ + SPARSE_BINOP_DECLS (A_T, F_T, T, friend, <>, A_T, T) \ + SPARSE_BINOP_DECLS (A_T, F_T, T, friend, <>, T, A_T) \ + SPARSE_AA_BINOP_DECLS (A_T, T, friend, <>) + +// Instantiate the binary operators. +#define SPARSE_BINOP_DEFS(A_T, F_T, E_T) \ + SPARSE_BINOP_DECLS (A_T, F_T, E_T, template, , A_T, E_T) \ + SPARSE_BINOP_DECLS (A_T, F_T, E_T, template, , E_T, A_T) \ + SPARSE_AA_BINOP_DECLS (A_T, E_T, template, ) + +// A function that can be used to forward binary operations from derived +// classes back to us. +#define SPARSE_BINOP_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T) \ + inline R \ + F (const X_T& x, const Y_T& y) \ + { \ + return R (F (C_X (x), C_Y (y))); \ + } + +// The binary operators that we care about forwarding. We have two +// sets of macros since the MSparse OP MSparse operations use functions +// (product and quotient) instead of operators (*, /). +#define SPARSE_BINOP_FWD_DEFS(R, F, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (F, operator +, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (F, operator -, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, operator *, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, operator /, T, C_X, X_T, C_Y, Y_T) + +#define SPARSE_AA_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, operator +, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, operator -, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, product, T, C_X, X_T, C_Y, Y_T) \ + SPARSE_BINOP_FWD_FCN (R, quotient, T, C_X, X_T, C_Y, Y_T) + +// Forward declarations for the MSparse operators. +#define SPARSE_OPS_FORWARD_DECLS(A_T, F_T) \ + template \ + class A_T; \ + \ + /* SPARSE_OP_ASSIGN_FWD_DECLS (A_T, T) */ \ + SPARSE_OP_ASSIGN_FWD_DECLS (A_T, A_T) \ + SPARSE_UNOP_FWD_DECLS (A_T) \ + SPARSE_BINOP_FWD_DECLS (A_T, F_T) + +// Friend declarations for the MSparse operators. +#define SPARSE_OPS_FRIEND_DECLS(A_T, F_T) \ + /* SPARSE_OP_ASSIGN_FRIENDS (A_T, T) */ \ + SPARSE_OP_ASSIGN_FRIENDS (A_T, A_T) \ + SPARSE_UNOP_FRIENDS (A_T) \ + SPARSE_BINOP_FRIENDS (A_T, F_T) + +// The following macros are for external use. + +// Instantiate all the MSparse friends for MSparse element type T. +#define INSTANTIATE_SPARSE_FRIENDS(T) \ + /* SPARSE_OP_ASSIGN_DEFS (MSparse, T, T) */ \ + SPARSE_OP_ASSIGN_DEFS (MSparse, T, MSparse) \ + SPARSE_UNOP_DEFS (MSparse, T) \ + SPARSE_BINOP_DEFS (MSparse, MArray2, T) + +// Define all the MSparse forwarding functions for return type R and +// MSparse element type T +#define SPARSE_FORWARD_DEFS(B, R, F, T) \ + /* SPARSE_OP_ASSIGN_FWD_DEFS */ \ + /* (R, T, dynamic_cast&>, R, , T) */ \ + \ + SPARSE_OP_ASSIGN_FWD_DEFS \ + (R, T, \ + dynamic_cast&>, R, dynamic_cast&>, R) \ + \ + SPARSE_UNOP_FWD_DEFS \ + (R, T, dynamic_cast&>, R) \ + \ + SPARSE_BINOP_FWD_DEFS \ + (R, F, T, dynamic_cast&>, R, , T) \ + \ + SPARSE_BINOP_FWD_DEFS \ + (R, F, T, , T, dynamic_cast&>, R) \ + \ + SPARSE_AA_BINOP_FWD_DEFS \ + (R, T, dynamic_cast&>, R, dynamic_cast&>, R) + +// Now we have all the definitions we need. + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/MSparse.cc b/liboctave/MSparse.cc new file mode 100644 --- /dev/null +++ b/liboctave/MSparse.cc @@ -0,0 +1,506 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "quit.h" +#include "lo-error.h" +#include "MArray2.h" +#include "Array-util.h" + +#include "MSparse.h" +#include "MSparse-defs.h" + +// sparse array with math ops. + +// Element by element MSparse by MSparse ops. + +template +MSparse& +operator += (MSparse& a, const MSparse& b) +{ + MSparse r; + + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("operator +=" , a_nr, a_nc, b_nr, b_nc); + else + { + r = MSparse (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = a.data(ja) + 0.; + jx++; + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = 0. + b.data(jb); + jx++; + jb++; + jb_lt_max= jb < jb_max; + } + else + { + if ((a.data(ja) + b.data(jb)) != 0.) + { + r.data(jx) = a.data(ja) + b.data(jb); + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + a = r.maybe_compress (); + } + + return a; +} + +template +MSparse& +operator -= (MSparse& a, const MSparse& b) +{ + MSparse r; + + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("operator -=" , a_nr, a_nc, b_nr, b_nc); + else + { + r = MSparse (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = a.data(ja) - 0.; + jx++; + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = 0. - b.data(jb); + jx++; + jb++; + jb_lt_max= jb < jb_max; + } + else + { + if ((a.data(ja) - b.data(jb)) != 0.) + { + r.data(jx) = a.data(ja) - b.data(jb); + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + a = r.maybe_compress (); + } + + return a; +} + +// Element by element MSparse by scalar ops. + +#define SPARSE_A2S_OP_1(OP) \ + template \ + MArray2 \ + operator OP (const MSparse& a, const T& s) \ + { \ + int nr = a.rows (); \ + int nc = a.cols (); \ + \ + MArray2 r (nr, nc, (0.0 OP s)); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = a.cidx(j); i < a.cidx(j+1); i++) \ + r.elem (a.ridx (i), j) = a.data (i) OP s; \ + return r; \ + } + +#define SPARSE_A2S_OP_2(OP) \ + template \ + MSparse \ + operator OP (const MSparse& a, const T& s) \ + { \ + int nr = a.rows (); \ + int nc = a.cols (); \ + int nz = a.nnz (); \ + \ + MSparse r (nr, nc, nz); \ + \ + for (int i = 0; i < nz; i++) \ + { \ + r.data(i) = a.data(i) OP s; \ + r.ridx(i) = a.ridx(i); \ + } \ + for (int i = 0; i < nc + 1; i++) \ + r.cidx(i) = a.cidx(i); \ + r.maybe_compress (true); \ + return r; \ + } + + +SPARSE_A2S_OP_1 (+) +SPARSE_A2S_OP_1 (-) +SPARSE_A2S_OP_2 (*) +SPARSE_A2S_OP_2 (/) + +// Element by element scalar by MSparse ops. + +#define SPARSE_SA2_OP_1(OP) \ + template \ + MArray2 \ + operator OP (const T& s, const MSparse& a) \ + { \ + int nr = a.rows (); \ + int nc = a.cols (); \ + \ + MArray2 r (nr, nc, (s OP 0.0)); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = a.cidx(j); i < a.cidx(j+1); i++) \ + r.elem (a.ridx (i), j) = s OP a.data (i); \ + return r; \ + } + +#define SPARSE_SA2_OP_2(OP) \ + template \ + MSparse \ + operator OP (const T& s, const MSparse& a) \ + { \ + int nr = a.rows (); \ + int nc = a.cols (); \ + int nz = a.nnz (); \ + \ + MSparse r (nr, nc, nz); \ + \ + for (int i = 0; i < nz; i++) \ + { \ + r.data(i) = s OP a.data(i); \ + r.ridx(i) = a.ridx(i); \ + } \ + for (int i = 0; i < nc + 1; i++) \ + r.cidx(i) = a.cidx(i); \ + r.maybe_compress (true); \ + return r; \ + } + +SPARSE_SA2_OP_1 (+) +SPARSE_SA2_OP_1 (-) +SPARSE_SA2_OP_2 (*) +SPARSE_SA2_OP_2 (/) + +// Element by element MSparse by MSparse ops. + +#define SPARSE_A2A2_OP(OP) \ + template \ + MSparse \ + operator OP (const MSparse& a, const MSparse& b) \ + { \ + MSparse r; \ + \ + int a_nr = a.rows (); \ + int a_nc = a.cols (); \ + \ + int b_nr = b.rows (); \ + int b_nc = b.cols (); \ + \ + if (a_nr != b_nr || a_nc != b_nc) \ + gripe_nonconformant ("operator " # OP, a_nr, a_nc, b_nr, b_nc); \ + else \ + { \ + r = MSparse (a_nr, a_nc, (a.nnz () + b.nnz ())); \ + \ + int jx = 0; \ + r.cidx (0) = 0; \ + for (int i = 0 ; i < a_nc ; i++) \ + { \ + int ja = a.cidx(i); \ + int ja_max = a.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = b.cidx(i); \ + int jb_max = b.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) \ + { \ + r.ridx(jx) = a.ridx(ja); \ + r.data(jx) = a.data(ja) OP 0.; \ + jx++; \ + ja++; \ + ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) \ + { \ + r.ridx(jx) = b.ridx(jb); \ + r.data(jx) = 0. OP b.data(jb); \ + jx++; \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + if ((a.data(ja) OP b.data(jb)) != 0.) \ + { \ + r.data(jx) = a.data(ja) OP b.data(jb); \ + r.ridx(jx) = a.ridx(ja); \ + jx++; \ + } \ + ja++; \ + ja_lt_max= ja < ja_max; \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + } \ + r.cidx(i+1) = jx; \ + } \ + \ + r.maybe_compress (); \ + } \ + \ + return r; \ + } + +#define SPARSE_A2A2_FCN_1(FCN, OP) \ + template \ + MSparse \ + FCN (const MSparse& a, const MSparse& b) \ + { \ + MSparse r; \ + \ + int a_nr = a.rows (); \ + int a_nc = a.cols (); \ + \ + int b_nr = b.rows (); \ + int b_nc = b.cols (); \ + \ + if (a_nr != b_nr || a_nc != b_nc) \ + gripe_nonconformant (#FCN, a_nr, a_nc, b_nr, b_nc); \ + else \ + { \ + r = MSparse (a_nr, a_nc, (a.nnz() > b.nnz() ? a.nnz() : b.nnz())); \ + \ + int jx = 0; \ + r.cidx (0) = 0; \ + for (int i = 0 ; i < a_nc ; i++) \ + { \ + int ja = a.cidx(i); \ + int ja_max = a.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = b.cidx(i); \ + int jb_max = b.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) \ + { \ + ja++; ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) \ + { \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + if ((a.data(ja) OP b.data(jb)) != 0.) \ + { \ + r.data(jx) = a.data(ja) OP b.data(jb); \ + r.ridx(jx) = a.ridx(ja); \ + jx++; \ + } \ + ja++; ja_lt_max= ja < ja_max; \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + } \ + r.cidx(i+1) = jx; \ + } \ + \ + r.maybe_compress (); \ + } \ + \ + return r; \ + } + +#define SPARSE_A2A2_FCN_2(FCN, OP) \ + template \ + MSparse \ + FCN (const MSparse& a, const MSparse& b) \ + { \ + MSparse r; \ + T Zero = T (); \ + \ + int a_nr = a.rows (); \ + int a_nc = a.cols (); \ + \ + int b_nr = b.rows (); \ + int b_nc = b.cols (); \ + \ + if (a_nr != b_nr || a_nc != b_nc) \ + gripe_nonconformant (#FCN, a_nr, a_nc, b_nr, b_nc); \ + else \ + { \ + r = MSparse( a_nr, a_nc, (Zero OP Zero)); \ + \ + for (int i = 0 ; i < a_nc ; i++) \ + { \ + int ja = a.cidx(i); \ + int ja_max = a.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = b.cidx(i); \ + int jb_max = b.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) \ + { \ + r.elem (a.ridx(ja),i) = a.data(ja) OP Zero; \ + ja++; ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) \ + { \ + r.elem (b.ridx(jb),i) = Zero OP b.data(jb); \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + r.elem (a.ridx(ja),i) = a.data(ja) OP b.data(jb); \ + ja++; ja_lt_max= ja < ja_max; \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + } \ + } \ + \ + r.maybe_compress (true); \ + } \ + \ + return r; \ + } + +SPARSE_A2A2_OP (+) +SPARSE_A2A2_OP (-) +SPARSE_A2A2_FCN_1 (product, *) +SPARSE_A2A2_FCN_2 (quotient, /) + +// Unary MSparse ops. + +template +MSparse +operator + (const MSparse& a) +{ + return a; +} + +template +MSparse +operator - (const MSparse& a) +{ + MSparse retval (a); + int nz = a.nnz (); + for (int i = 0; i < nz; i++) + retval.data(i) = - retval.data(i); + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/MSparse.h b/liboctave/MSparse.h new file mode 100644 --- /dev/null +++ b/liboctave/MSparse.h @@ -0,0 +1,116 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_MSparse_h) +#define octave_MSparse_h 1 + +#include "MArray2.h" + +#include "Sparse.h" + +// Two dimensional sparse array with math ops. + +// But first, some preprocessor abuse... + +#include "MSparse-defs.h" + +SPARSE_OPS_FORWARD_DECLS (MSparse, MArray2) + +template +class +MSparse : public Sparse +{ +public: + + MSparse (void) : Sparse () { } + + MSparse (int n, int m) : Sparse (n, m) { } + + MSparse (const MSparse& a) : Sparse (a) { } + + MSparse (const MSparse& a, const dim_vector& dv) : Sparse (a, dv) { } + + MSparse (const Sparse& a) : Sparse (a) { } + + MSparse (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : Sparse (a, r, c, nr, nc, sum_terms) { } + + MSparse (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : Sparse (a, r, c, nr, nc, sum_terms) { } + + explicit MSparse (int r, int c, T val) : Sparse (r, c, val) { } + + MSparse (int r, int c, int num_nz) : Sparse (r, c, num_nz) { } + + ~MSparse (void) { } + + MSparse& operator = (const MSparse& a) + { + Sparse::operator = (a); + return *this; + } + + MSparse& insert (const Sparse& a, int r, int c) + { + Sparse::insert (a, r, c); + return *this; + } + + MSparse transpose (void) const { return Sparse::transpose (); } + + MSparse squeeze (void) const { return Sparse::squeeze (); } + + MSparse index (idx_vector& i, int resize_ok) const + { return Sparse::index (i, resize_ok); } + + MSparse index (idx_vector& i, idx_vector& j, int resize_ok) const + { return Sparse::index (i, j, resize_ok); } + + MSparse index (Array& ra_idx, int resize_ok) const + { return Sparse::index (ra_idx, resize_ok); } + + MSparse reshape (const dim_vector& new_dims) const + { return Sparse::reshape (new_dims); } + + MSparse permute (const Array& vec, bool inv = false) const + { return Sparse::permute (vec, inv); } + + MSparse ipermute (const Array& vec) const + { return Sparse::ipermute (vec); } + + + // Currently, the OPS functions don't need to be friends, but that + // may change. + + // SPARSE_OPS_FRIEND_DECLS (MSparse, MArray2) +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Makefile.in b/liboctave/Makefile.in --- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -10,7 +10,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ -VPATH = @srcdir@ +VPATH = @srcdir@:@srcdir@/COLAMD include $(TOPDIR)/Makeconf @@ -22,6 +22,10 @@ -L../libcruft -L../glob -L. $(RLD_FLAG) \ $(LIBCRUFT) $(BLAS_LIBS) $(FFTW_LIBS) $(LIBREADLINE) -lglob $(LIBS) $(FLIBS) +include $(srcdir)/COLAMD.files + +include $(srcdir)/UMFPACK.files + MATRIX_INC := Array.h Array2.h Array3.h ArrayN.h DiagArray2.h \ Array-flags.h Array-util.h ArrayN-idx.h MArray-defs.h \ MArray.h MArray2.h MDiagArray2.h Matrix.h MArrayN.h \ @@ -33,6 +37,9 @@ chMatrix.h chNDArray.h dColVector.h dDiagMatrix.h dMatrix.h \ dNDArray.h dRowVector.h dbleAEPBAL.h dbleCHOL.h dbleDET.h \ dbleHESS.h dbleLU.h dbleQR.h dbleQRP.h dbleSCHUR.h dbleSVD.h \ + boolSparse.h CSparse.h dSparse.h MSparse-defs.h MSparse.h \ + Sparse.h oct-spparms.h sparse-base-lu.h SparseCmplxLU.h \ + SparsedbleLU.h Sparse-op-defs.h SparseType.h \ int8NDArray.h uint8NDArray.h int16NDArray.h uint16NDArray.h \ int32NDArray.h uint32NDArray.h int64NDArray.h uint64NDArray.h \ intNDArray.h @@ -41,6 +48,8 @@ VX_OP_INC := $(shell $(AWK) -f $(srcdir)/mk-ops.awk prefix=vx list_h_files=1 $(srcdir)/vx-ops) +SPARSE_MX_OP_INC := $(shell $(AWK) -f $(srcdir)/sparse-mk-ops.awk prefix=smx list_h_files=1 $(srcdir)/sparse-mx-ops) + OPTS_INC_DATA := DASPK-opts.in DASRT-opts.in DASSL-opts.in \ LSODE-opts.in NLEqn-opts.in ODESSA-opts.in Quad-opts.in @@ -58,21 +67,24 @@ lo-sysdep.h lo-utils.h mach-info.h oct-alloc.h oct-cmplx.h \ oct-env.h oct-fftw.h oct-getopt.h oct-group.h oct-inttypes.h \ oct-passwd.h oct-rand.h oct-rl-edit.h oct-rl-hist.h \ - oct-shlib.h oct-sort.h oct-syscalls.h oct-time.h pathlen.h \ - pathsearch.h prog-args.h so-array.h statdefs.h str-vec.h \ - sun-utils.h sysdir.h systime.h syswait.h \ + oct-shlib.h oct-sort.h oct-spparms.h oct-syscalls.h \ + oct-time.h pathlen.h pathsearch.h prog-args.h so-array.h \ + sparse-sort.h statdefs.h str-vec.h sun-utils.h sysdir.h \ + systime.h syswait.h \ $(OPTS_INC) \ $(MATRIX_INC) \ $(MX_OP_INC) \ - $(VX_OP_INC) + $(VX_OP_INC) \ + $(SPARSE_MX_OP_INC) TEMPLATE_SRC := Array.cc ArrayN.cc DiagArray2.cc \ MArray.cc MArray2.cc MArrayN.cc MDiagArray2.cc \ - base-lu.cc oct-sort.cc + base-lu.cc oct-sort.cc sparse-base-lu.cc TI_SRC := Array-C.cc Array-b.cc Array-ch.cc Array-i.cc Array-d.cc \ Array-s.cc Array-so.cc Array-str.cc Array-idx-vec.cc \ MArray-C.cc MArray-ch.cc MArray-i.cc MArray-d.cc MArray-s.cc \ + MSparse-C.cc MSparse-d.cc Sparse-C.cc Sparse-b.cc Sparse-d.cc \ oct-inttypes.cc MATRIX_SRC := Array-flags.cc Array-util.cc CColVector.cc \ @@ -83,7 +95,9 @@ chNDArray.cc dColVector.cc dDiagMatrix.cc dMatrix.cc \ dNDArray.cc dRowVector.cc dbleAEPBAL.cc dbleCHOL.cc \ dbleDET.cc dbleHESS.cc dbleLU.cc dbleQR.cc dbleQRP.cc \ - dbleSCHUR.cc dbleSVD.cc \ + dbleSCHUR.cc dbleSVD.cc boolSparse.cc CSparse.cc dSparse.cc \ + MSparse.cc Sparse.cc SparseCmplxLU.cc SparsedbleLU.cc \ + SparseType.cc \ int8NDArray.cc uint8NDArray.cc int16NDArray.cc uint16NDArray.cc \ int32NDArray.cc uint32NDArray.cc int64NDArray.cc uint64NDArray.cc @@ -91,6 +105,8 @@ VX_OP_SRC := $(shell $(AWK) -f $(srcdir)/mk-ops.awk prefix=vx list_cc_files=1 $(srcdir)/vx-ops) +SPARSE_MX_OP_SRC := $(shell $(AWK) -f $(srcdir)/sparse-mk-ops.awk prefix=smx list_cc_files=1 $(srcdir)/sparse-mx-ops) + LIBOCTAVE_CXX_SOURCES := Bounds.cc CollocWt.cc \ DASPK.cc DASRT.cc DASSL.cc FEGrid.cc LinConst.cc \ LPsolve.cc LSODE.cc NLEqn.cc ODES.cc ODESSA.cc \ @@ -99,12 +115,14 @@ lo-ieee.cc lo-mappers.cc lo-specfun.cc lo-sysdep.cc \ lo-utils.cc mach-info.cc oct-alloc.cc oct-env.cc \ oct-fftw.cc oct-group.cc oct-passwd.cc oct-rand.cc oct-shlib.cc \ - oct-syscalls.cc oct-time.cc prog-args.cc so-array.cc str-vec.cc \ + oct-spparms.cc oct-syscalls.cc oct-time.cc prog-args.cc \ + so-array.cc sparse-sort.cc str-vec.cc \ $(TEMPLATE_SRC) \ $(TI_SRC) \ $(MATRIX_SRC) \ $(MX_OP_SRC) \ - $(VX_OP_SRC) + $(VX_OP_SRC) \ + $(SPARSE_MX_OP_SRC) LIBOCTAVE_C_SOURCES := f2c-main.c filemode.c getopt.c getopt1.c \ lo-cieee.c lo-cutils.c mkdir.c oct-getopt.c rename.c \ @@ -135,17 +153,25 @@ INCLUDES_FOR_INSTALL := $(INCLUDES) $(TEMPLATE_SRC) $(EXTRAS) DISTFILES := Makefile.in ChangeLog mk-ops.awk mx-ops vx-ops \ - $(SOURCES) $(INCLUDES) $(EXTRAS) $(OPTS_INC_DATA) + sparse-mk-ops.awk sparse-mx-ops \ + $(SOURCES) $(INCLUDES) $(EXTRAS) $(OPTS_INC_DATA) \ + $(COLAMD_EXTRAS) $(UMFPACK_EXTRAS) + +# Complete directory trees to distribute. +DISTDIRS := COLAMD UMFPACK ifeq ($(SHARED_LIBS), true) BINDISTLIBS = liboctave/liboctave BINDISTFILES = liboctave.$(SHLEXT_VER) endif -MAKEDEPS_1 := $(patsubst %.cc, %.d, $(SOURCES)) +MAKEDEPS_2 := $(SOURCES) $(COLAMD_SRC) +MAKEDEPS_1 := $(patsubst %.cc, %.d, $(MAKEDEPS_2)) MAKEDEPS := $(patsubst %.c, %.d, $(MAKEDEPS_1)) LIBOCTAVE_OBJECTS := \ + $(COLAMD_OBJ) \ + $(UMFPACK_OBJ) \ $(LIBOCTAVE_CXX_SOURCES:.cc=.o) \ $(LIBOCTAVE_C_SOURCES:.c=.o) \ $(LIBOCT_READLINE_CXX_SOURCES:.cc=.o) \ @@ -161,11 +187,20 @@ endif endif +UMFPACK_SPECIAL_1 := CSparse.o dSparse.o SparseCmplxLU.o SparsedbleLU.o +UMFPACK_SPECIAL := \ + $(UMFPACK_SPECIAL_1) \ + $(addprefix pic/, $(UMFPACK_SPECIAL_1)) \ + $(UMFPACK_SPECIAL_1:.o=.d) +$(UMFPACK_SPECIAL): INCFLAGS += $(UMFPACK_INCFLAGS) + all: libraries .PHONY: all objects: $(OBJECTS) +include $(srcdir)/UMFPACK.rules + stmp-pic: pic @if [ -f stmp-pic ]; then \ true; \ @@ -182,7 +217,9 @@ mkdir pic; \ fi -stamp-prereq: $(OPTS_INC) $(VX_OP_INC) $(VX_OP_SRC) $(MX_OP_INC) $(MX_OP_SRC) mx-ops.h +stamp-prereq: $(OPTS_INC) $(VX_OP_INC) $(VX_OP_SRC) \ + $(MX_OP_INC) $(MX_OP_SRC) mx-ops.h \ + $(SPARSE_MX_OP_INC) $(SPARSE_MX_OP_SRC) touch stamp-prereq ifeq ($(SHARED_LIBS), true) @@ -296,6 +333,7 @@ distclean: clean rm -f Makefile so_locations stamp-prereq $(OPTS_INC) rm -f mx-ops.h $(MX_OP_INC) $(VX_OP_INC) $(MX_OP_SRC) $(VX_OP_SRC) + rm -f $(SPARSE_MX_OP_INC) $(SPARSE_MX_OP_SRC) .PHONY: distclean maintainer-clean: distclean @@ -304,6 +342,7 @@ dist: stamp-prereq ln $(DISTFILES) ../`cat ../.fname`/liboctave + for dir in $(DISTDIRS); do ln -s ../../liboctave/$$dir ../`cat ../.fname/liboctave`; done .PHONY: dist bin-dist: @@ -326,6 +365,9 @@ $(MX_OP_INC) $(MX_OP_SRC) : $(srcdir)/mk-ops.awk mx-ops $(AWK) -f $(srcdir)/mk-ops.awk prefix=mx $(srcdir)/mx-ops +$(SPARSE_MX_OP_INC) $(SPARSE_MX_OP_SRC) : $(srcdir)/sparse-mk-ops.awk sparse-mx-ops + $(AWK) -f $(srcdir)/sparse-mk-ops.awk prefix=smx $(srcdir)/sparse-mx-ops + mx-ops.h : $(srcdir)/mk-ops.awk mx-ops $(AWK) -f $(srcdir)/mk-ops.awk prefix=mx make_inclusive_header=mx-ops.h $(srcdir)/mx-ops > $@-t $(top_srcdir)/move-if-change $@-t $@ diff --git a/liboctave/Sparse-C.cc b/liboctave/Sparse-C.cc new file mode 100644 --- /dev/null +++ b/liboctave/Sparse-C.cc @@ -0,0 +1,45 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +// Instantiate Sparse matrix of complex values. + +#include "oct-cmplx.h" + +#include "Sparse.h" +#include "Sparse.cc" + +INSTANTIATE_SPARSE_AND_ASSIGN (Complex); + +INSTANTIATE_SPARSE_ASSIGN (Complex, double); + +#if 0 +template std::ostream& operator << (std::ostream&, const Sparse&); +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Sparse-b.cc b/liboctave/Sparse-b.cc new file mode 100644 --- /dev/null +++ b/liboctave/Sparse-b.cc @@ -0,0 +1,41 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +// Instantiate Sparse matrix of double values. + +#include "Sparse.h" +#include "Sparse.cc" + +INSTANTIATE_SPARSE_AND_ASSIGN (bool); + +#if 0 +template std::ostream& operator << (std::ostream&, const Sparse&); +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Sparse-d.cc b/liboctave/Sparse-d.cc new file mode 100644 --- /dev/null +++ b/liboctave/Sparse-d.cc @@ -0,0 +1,41 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +// Instantiate Sparse matrix of double values. + +#include "Sparse.h" +#include "Sparse.cc" + +INSTANTIATE_SPARSE_AND_ASSIGN (double); + +#if 0 +template std::ostream& operator << (std::ostream&, const Sparse&); +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Sparse-op-defs.h b/liboctave/Sparse-op-defs.h new file mode 100644 --- /dev/null +++ b/liboctave/Sparse-op-defs.h @@ -0,0 +1,1609 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_op_defs_h) +#define octave_sparse_op_defs_h 1 + +#include "Array-util.h" + +#define SPARSE_BIN_OP_DECL(R, OP, X, Y) \ + extern R OP (const X&, const Y&) + +#define SPARSE_CMP_OP_DECL(OP, X, Y) \ + extern SparseBoolMatrix OP (const X&, const Y&) + +#define SPARSE_BOOL_OP_DECL(OP, X, Y) \ + extern SparseBoolMatrix OP (const X&, const Y&) + +// matrix by scalar operations. + +#define SPARSE_SMS_BIN_OP_DECLS(R1, R2, M, S) \ + SPARSE_BIN_OP_DECL (R1, operator +, M, S); \ + SPARSE_BIN_OP_DECL (R1, operator -, M, S); \ + SPARSE_BIN_OP_DECL (R2, operator *, M, S); \ + SPARSE_BIN_OP_DECL (R2, operator /, M, S); + +#define SPARSE_SMS_BIN_OP_1(R, F, OP, M, S) \ + R \ + F (const M& m, const S& s) \ + { \ + int nr = m.rows (); \ + int nc = m.cols (); \ + \ + R r (nr, nc, (0.0 OP s)); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = m.cidx (j); i < m.cidx (j+1); i++) \ + r.elem (m.ridx (i), j) = m.data (i) OP s; \ + return r; \ + } + +#define SPARSE_SMS_BIN_OP_2(R, F, OP, M, S) \ + R \ + F (const M& m, const S& s) \ + { \ + int nr = m.rows (); \ + int nc = m.cols (); \ + int nz = m.nnz (); \ + \ + R r (nr, nc, nz); \ + \ + for (int i = 0; i < nz; i++) \ + { \ + r.data(i) = m.data(i) OP s; \ + r.ridx(i) = m.ridx(i); \ + } \ + for (int i = 0; i < nc + 1; i++) \ + r.cidx(i) = m.cidx(i); \ + \ + r.maybe_compress (true); \ + return r; \ + } + +#define SPARSE_SMS_BIN_OPS(R1, R2, M, S) \ + SPARSE_SMS_BIN_OP_1 (R1, operator +, +, M, S) \ + SPARSE_SMS_BIN_OP_1 (R1, operator -, -, M, S) \ + SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \ + SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S) + +#define SPARSE_SMS_CMP_OP_DECLS(M, S) \ + SPARSE_CMP_OP_DECL (mx_el_lt, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_le, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_ge, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_gt, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_eq, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M, S); + +#define SPARSE_SMS_EQNE_OP_DECLS(M, S) \ + SPARSE_CMP_OP_DECL (mx_el_eq, M, S); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M, S); + +#define SPARSE_SMS_CMP_OP(F, OP, M, MZ, MC, S, SZ, SC) \ + SparseBoolMatrix \ + F (const M& m, const S& s) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + int nz = m.nnz (); \ + if (MC (MZ) OP SC (s)) \ + nel += m.numel() - nz; \ + for (int i = 0; i < nz; i++) \ + if (MC (m.data (i)) OP SC (s)) \ + nel++; \ + \ + int nr = m.rows (); \ + int nc = m.cols (); \ + SparseBoolMatrix r (nr, nc, nel); \ + \ + if (nr > 0 && nc > 0) \ + { \ + if (MC (MZ) OP SC (s)) \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = 0; i < nr; i++) \ + { \ + bool el = MC (m.elem(i, j)) OP SC (s); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + else \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = m.cidx(j); i < m.cidx(j+1); i++) \ + { \ + bool el = MC (m.data(i)) OP SC (s); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = m.ridx(i); \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + return r; \ + } + +#define SPARSE_SMS_CMP_OPS(M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_lt, <, M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_le, <=, M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_gt, >, M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ, , S, SZ, ) \ + SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ, , S, SZ, ) + +#define SPARSE_SMS_EQNE_OPS(M, MZ, CM, S, SZ, CS) \ + SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ, , S, SZ, ) \ + SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ, , S, SZ, ) + +#define SPARSE_SMS_BOOL_OP_DECLS(M, S) \ + SPARSE_BOOL_OP_DECL (mx_el_and, M, S); \ + SPARSE_BOOL_OP_DECL (mx_el_or, M, S); + +#define SPARSE_SMS_BOOL_OP(F, OP, M, S, LHS_ZERO, RHS_ZERO) \ + SparseBoolMatrix \ + F (const M& m, const S& s) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + int nz = m.nnz (); \ + if (LHS_ZERO OP (s != RHS_ZERO)) \ + nel += m.numel() - nz; \ + for (int i = 0; i < nz; i++) \ + if ((m.data(i) != LHS_ZERO) OP (s != RHS_ZERO))\ + nel++; \ + \ + int nr = m.rows (); \ + int nc = m.cols (); \ + SparseBoolMatrix r (nr, nc, nel); \ + \ + if (nr > 0 && nc > 0) \ + { \ + if (LHS_ZERO OP (s != RHS_ZERO)) \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = 0; i < nr; i++) \ + { \ + bool el = (m.elem(i, j) != LHS_ZERO) OP (s != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + else \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = m.cidx(j); i < m.cidx(j+1); i++) \ + { \ + bool el = (m.data(i) != LHS_ZERO) OP (s != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = m.ridx(i); \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + return r; \ + } + +#define SPARSE_SMS_BOOL_OPS2(M, S, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMS_BOOL_OP (mx_el_and, &&, M, S, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMS_BOOL_OP (mx_el_or, ||, M, S, LHS_ZERO, RHS_ZERO) + +#define SPARSE_SMS_BOOL_OPS(M, S, ZERO) \ + SPARSE_SMS_BOOL_OPS2(M, S, ZERO, ZERO) + +#define SPARSE_SMS_OP_DECLS(R1, R2, M, S) \ + SPARSE_SMS_BIN_OP_DECLS (R1, R2, M, S) \ + SPARSE_SMS_CMP_OP_DECLS (M, S) \ + SPARSE_SMS_BOOL_OP_DECLS (M, S) + +// scalar by matrix operations. + +#define SPARSE_SSM_BIN_OP_DECLS(R1, R2, S, M) \ + SPARSE_BIN_OP_DECL (R1, operator +, S, M); \ + SPARSE_BIN_OP_DECL (R1, operator -, S, M); \ + SPARSE_BIN_OP_DECL (R2, operator *, S, M); \ + SPARSE_BIN_OP_DECL (R2, operator /, S, M); + +#define SPARSE_SSM_BIN_OP_1(R, F, OP, S, M) \ + R \ + F (const S& s, const M& m) \ + { \ + int nr = m.rows (); \ + int nc = m.cols (); \ + \ + R r (nr, nc, (s OP 0.0)); \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = m.cidx (j); i < m.cidx (j+1); i++) \ + r.elem (m.ridx (i), j) = s OP m.data (i); \ + \ + return r; \ + } + +#define SPARSE_SSM_BIN_OP_2(R, F, OP, S, M) \ + R \ + F (const S& s, const M& m) \ + { \ + int nr = m.rows (); \ + int nc = m.cols (); \ + int nz = m.nnz (); \ + \ + R r (nr, nc, nz); \ + \ + for (int i = 0; i < nz; i++) \ + { \ + r.data(i) = s OP m.data(i); \ + r.ridx(i) = m.ridx(i); \ + } \ + for (int i = 0; i < nc + 1; i++) \ + r.cidx(i) = m.cidx(i); \ + \ + r.maybe_compress(true); \ + return r; \ + } + +#define SPARSE_SSM_BIN_OPS(R1, R2, S, M) \ + SPARSE_SSM_BIN_OP_1 (R1, operator +, +, S, M) \ + SPARSE_SSM_BIN_OP_1 (R1, operator -, -, S, M) \ + SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \ + SPARSE_SSM_BIN_OP_2 (R2, operator /, /, S, M) + +#define SPARSE_SSM_CMP_OP_DECLS(S, M) \ + SPARSE_CMP_OP_DECL (mx_el_lt, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_le, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_ge, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_gt, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_eq, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_ne, S, M); + +#define SPARSE_SSM_EQNE_OP_DECLS(S, M) \ + SPARSE_CMP_OP_DECL (mx_el_eq, S, M); \ + SPARSE_CMP_OP_DECL (mx_el_ne, S, M); + +#define SPARSE_SSM_CMP_OP(F, OP, S, SZ, SC, M, MZ, MC) \ + SparseBoolMatrix \ + F (const S& s, const M& m) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + int nz = m.nnz (); \ + if (SC (s) OP MC (MZ)) \ + nel += m.numel() - nz; \ + for (int i = 0; i < nz; i++) \ + if (SC (s) OP MC (m.data (i))) \ + nel++; \ + \ + int nr = m.rows (); \ + int nc = m.cols (); \ + SparseBoolMatrix r (nr, nc, nel); \ + \ + if (nr > 0 && nc > 0) \ + { \ + if (SC (s) OP MC (MZ))\ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = 0; i < nr; i++) \ + { \ + bool el = SC (s) OP MC (m.elem(i, j)); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + else \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = m.cidx(j); i < m.cidx(j+1); i++) \ + { \ + bool el = SC (s) OP MC (m.data(i)); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = m.ridx(i); \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + return r; \ + } + +#define SPARSE_SSM_CMP_OPS(S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_lt, <, S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_le, <=, S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_gt, >, S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ, , M, MZ, ) \ + SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ, , M, MZ, ) + +#define SPARSE_SSM_EQNE_OPS(S, SZ, SC, M, MZ, MC) \ + SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ, , M, MZ, ) \ + SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ, , M, MZ, ) + +#define SPARSE_SSM_BOOL_OP_DECLS(S, M) \ + SPARSE_BOOL_OP_DECL (mx_el_and, S, M); \ + SPARSE_BOOL_OP_DECL (mx_el_or, S, M); \ + +#define SPARSE_SSM_BOOL_OP(F, OP, S, M, LHS_ZERO, RHS_ZERO) \ + SparseBoolMatrix \ + F (const S& s, const M& m) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + int nz = m.nnz (); \ + if ((s != LHS_ZERO) OP RHS_ZERO) \ + nel += m.numel() - nz; \ + for (int i = 0; i < nz; i++) \ + if ((s != LHS_ZERO) OP m.data(i) != RHS_ZERO) \ + nel++; \ + \ + int nr = m.rows (); \ + int nc = m.cols (); \ + SparseBoolMatrix r (nr, nc, nel); \ + \ + if (nr > 0 && nc > 0) \ + { \ + if ((s != LHS_ZERO) OP RHS_ZERO) \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = 0; i < nr; i++) \ + { \ + bool el = (s != LHS_ZERO) OP (m.elem(i, j) != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + else \ + { \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < nc; j++) \ + { \ + for (int i = m.cidx(j); i < m.cidx(j+1); i++) \ + { \ + bool el = (s != LHS_ZERO) OP (m.data(i) != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = m.ridx(i); \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + return r; \ + } + +#define SPARSE_SSM_BOOL_OPS2(S, M, LHS_ZERO, RHS_ZERO) \ + SPARSE_SSM_BOOL_OP (mx_el_and, &&, S, M, LHS_ZERO, RHS_ZERO) \ + SPARSE_SSM_BOOL_OP (mx_el_or, ||, S, M, LHS_ZERO, RHS_ZERO) + +#define SPARSE_SSM_BOOL_OPS(S, M, ZERO) \ + SPARSE_SSM_BOOL_OPS2(S, M, ZERO, ZERO) + +#define SPARSE_SSM_OP_DECLS(R1, R2, S, M) \ + SPARSE_SSM_BIN_OP_DECLS (R1, R2, S, M) \ + SPARSE_SSM_CMP_OP_DECLS (S, M) \ + SPARSE_SSM_BOOL_OP_DECLS (S, M) \ + +// matrix by matrix operations. + +#define SPARSE_SMSM_BIN_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_BIN_OP_DECL (R1, operator +, M1, M2); \ + SPARSE_BIN_OP_DECL (R1, operator -, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, product, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, quotient, M1, M2); + +#define SPARSE_SMSM_BIN_OP_1(R, F, OP, M1, M2) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + r = R (m1_nr, m1_nc, (m1.nnz () + m2.nnz ())); \ + \ + int jx = 0; \ + r.cidx (0) = 0; \ + for (int i = 0 ; i < m1_nc ; i++) \ + { \ + int ja = m1.cidx(i); \ + int ja_max = m1.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = m2.cidx(i); \ + int jb_max = m2.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ + { \ + r.ridx(jx) = m1.ridx(ja); \ + r.data(jx) = m1.data(ja) OP 0.; \ + jx++; \ + ja++; \ + ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ + { \ + r.ridx(jx) = m2.ridx(jb); \ + r.data(jx) = 0. OP m2.data(jb); \ + jx++; \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + if ((m1.data(ja) OP m2.data(jb)) != 0.) \ + { \ + r.data(jx) = m1.data(ja) OP m2.data(jb); \ + r.ridx(jx) = m1.ridx(ja); \ + jx++; \ + } \ + ja++; \ + ja_lt_max= ja < ja_max; \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + } \ + r.cidx(i+1) = jx; \ + } \ + \ + r.maybe_compress (); \ + } \ + \ + return r; \ + } + +#define SPARSE_SMSM_BIN_OP_2(R, F, OP, M1, M2) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + r = R (m1_nr, m1_nc, (m1.nnz () > m2.nnz () ? m1.nnz () : m2.nnz ())); \ + \ + int jx = 0; \ + r.cidx (0) = 0; \ + for (int i = 0 ; i < m1_nc ; i++) \ + { \ + int ja = m1.cidx(i); \ + int ja_max = m1.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = m2.cidx(i); \ + int jb_max = m2.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ + { \ + ja++; ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ + { \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + if ((m1.data(ja) OP m2.data(jb)) != 0.) \ + { \ + r.data(jx) = m1.data(ja) OP m2.data(jb); \ + r.ridx(jx) = m1.ridx(ja); \ + jx++; \ + } \ + ja++; ja_lt_max= ja < ja_max; \ + jb++; jb_lt_max= jb < jb_max; \ + } \ + } \ + r.cidx(i+1) = jx; \ + } \ + \ + r.maybe_compress (); \ + } \ + \ + return r; \ + } + +#define SPARSE_SMSM_BIN_OP_3(R, F, OP, M1, M2) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + \ + /* XXX FIXME XXX Kludge... Always double/Complex, so Complex () */ \ + r = R (m1_nr, m1_nc, (Complex () OP Complex ())); \ + \ + for (int i = 0 ; i < m1_nc ; i++) \ + { \ + int ja = m1.cidx(i); \ + int ja_max = m1.cidx(i+1); \ + bool ja_lt_max= ja < ja_max; \ + \ + int jb = m2.cidx(i); \ + int jb_max = m2.cidx(i+1); \ + bool jb_lt_max = jb < jb_max; \ + \ + while (ja_lt_max || jb_lt_max ) \ + { \ + OCTAVE_QUIT; \ + if ((! jb_lt_max) || \ + (ja_lt_max && (m1.ridx(ja) < m2.ridx(jb)))) \ + { \ + /* keep those kludges coming */ \ + r.elem(m1.ridx(ja),i) = m1.data(ja) OP Complex (); \ + ja++; \ + ja_lt_max= ja < ja_max; \ + } \ + else if (( !ja_lt_max ) || \ + (jb_lt_max && (m2.ridx(jb) < m1.ridx(ja)) ) ) \ + { \ + /* keep those kludges coming */ \ + r.elem(m2.ridx(jb),i) = Complex () OP m2.data(jb); \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + else \ + { \ + r.elem(m1.ridx(ja),i) = m1.data(ja) OP m2.data(jb); \ + ja++; \ + ja_lt_max= ja < ja_max; \ + jb++; \ + jb_lt_max= jb < jb_max; \ + } \ + } \ + } \ + r.maybe_compress (true); \ + } \ + \ + return r; \ + } + +// Note that SM ./ SM needs to take into account the NaN and Inf values +// implied by the division by zero. +// XXX FIXME XXX Are the NaNs double(NaN) or Complex(NaN,Nan) in the complex +// case? +#define SPARSE_SMSM_BIN_OPS(R1, R2, M1, M2) \ + SPARSE_SMSM_BIN_OP_1 (R1, operator +, +, M1, M2) \ + SPARSE_SMSM_BIN_OP_1 (R1, operator -, -, M1, M2) \ + SPARSE_SMSM_BIN_OP_2 (R2, product, *, M1, M2) \ + SPARSE_SMSM_BIN_OP_3 (R2, quotient, /, M1, M2) + +#define SPARSE_SMSM_CMP_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_le, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_SMSM_EQNE_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_SMSM_CMP_OP(F, OP, M1, C1, M2, C2) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_SMSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_SMSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2) \ + SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2); \ + SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2); + +#define SPARSE_SMSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if ((m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO)) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = (m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_SMSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ + +#define SPARSE_SMSM_BOOL_OPS(M1, M2, ZERO) \ + SPARSE_SMSM_BOOL_OPS2(M1, M2, ZERO, ZERO) + +#define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2) \ + SPARSE_SMSM_CMP_OP_DECLS (M1, M2) \ + SPARSE_SMSM_BOOL_OP_DECLS (M1, M2) + +// matrix by matrix operations. + +#define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_BIN_OP_DECL (R1, operator +, M1, M2); \ + SPARSE_BIN_OP_DECL (R1, operator -, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, product, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, quotient, M1, M2); + +#define SPARSE_MSM_BIN_OP_1(R, F, OP, M1, M2) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + r = R (m1_nr, m1_nc); \ + \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ + } \ + return r; \ + } + +#define SPARSE_MSM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ + nel++; \ + \ + r = R (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0 ; j < m1_nc ; j++) \ + { \ + for (int i = 0 ; i < m1_nr ; i++) \ + { \ + if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ + { \ + r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ + r.ridx (ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + \ + return r; \ + } + +// XXX FIXME XXX Pass a specific ZERO value +#define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2) \ + SPARSE_MSM_BIN_OP_1 (R1, operator +, +, M1, M2) \ + SPARSE_MSM_BIN_OP_1 (R1, operator -, -, M1, M2) \ + SPARSE_MSM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ + SPARSE_MSM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) + +#define SPARSE_MSM_CMP_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_le, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_MSM_EQNE_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_MSM_CMP_OP(F, OP, M1, C1, M2, C2) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_MSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_MSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_MSM_BOOL_OP_DECLS(M1, M2) \ + SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2); \ + SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2); + +#define SPARSE_MSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if ((m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO)) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = (m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_MSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_MSM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ + +#define SPARSE_MSM_BOOL_OPS(M1, M2, ZERO) \ + SPARSE_MSM_BOOL_OPS2(M1, M2, ZERO, ZERO) + +#define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2) \ + SPARSE_MSM_CMP_OP_DECLS (M1, M2) \ + SPARSE_MSM_BOOL_OP_DECLS (M1, M2) + +// matrix by matrix operations. + +#define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_BIN_OP_DECL (R1, operator +, M1, M2); \ + SPARSE_BIN_OP_DECL (R1, operator -, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, product, M1, M2); \ + SPARSE_BIN_OP_DECL (R2, quotient, M1, M2); + +#define SPARSE_SMM_BIN_OP_1(R, F, OP, M1, M2) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + r = R (m1_nr, m1_nc); \ + \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + r.elem (i, j) = m1.elem (i, j) OP m2.elem (i, j); \ + } \ + return r; \ + } + +#define SPARSE_SMM_BIN_OP_2(R, F, OP, M1, M2, ZERO) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + else \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ + nel++; \ + \ + r = R (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0 ; j < m1_nc ; j++) \ + { \ + for (int i = 0 ; i < m1_nr ; i++) \ + { \ + if ((m1.elem(i, j) OP m2.elem(i, j)) != ZERO) \ + { \ + r.data (ii) = m1.elem(i, j) OP m2.elem(i,j); \ + r.ridx (ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + \ + return r; \ + } + +// XXX FIXME XXX Pass a specific ZERO value +#define SPARSE_SMM_BIN_OPS(R1, R2, M1, M2) \ + SPARSE_SMM_BIN_OP_1 (R1, operator +, +, M1, M2) \ + SPARSE_SMM_BIN_OP_1 (R1, operator -, -, M1, M2) \ + SPARSE_SMM_BIN_OP_2 (R2, product, *, M1, M2, 0.0) \ + SPARSE_SMM_BIN_OP_2 (R2, quotient, /, M1, M2, 0.0) + +#define SPARSE_SMM_CMP_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_le, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_SMM_EQNE_OP_DECLS(M1, M2) \ + SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2); \ + SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2); + +#define SPARSE_SMM_CMP_OP(F, OP, M1, C1, M2, C2) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if (C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j))) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = C1 (m1.elem(i, j)) OP C2 (m2.elem(i, j)); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_SMM_CMP_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_lt, <, M1, C1, M2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, C1, M2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, C1, M2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_gt, >, M1, C1, M2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_SMM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2) \ + SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, , M2, ) \ + SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, , M2, ) + +#define SPARSE_SMM_BOOL_OP_DECLS(M1, M2) \ + SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2); \ + SPARSE_BOOL_OP_DECL (mx_el_or, M1, M2); + +#define SPARSE_SMM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \ + SparseBoolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + SparseBoolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + /* Count num of non-zero elements */ \ + int nel = 0; \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + if ((m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO)) \ + nel++; \ + \ + r = SparseBoolMatrix (m1_nr, m1_nc, nel); \ + \ + int ii = 0; \ + r.cidx (0) = 0; \ + for (int j = 0; j < m1_nc; j++) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + { \ + bool el = (m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO); \ + if (el) \ + { \ + r.data(ii) = el; \ + r.ridx(ii++) = i; \ + } \ + } \ + r.cidx(j+1) = ii; \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + return r; \ + } + +#define SPARSE_SMM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \ + SPARSE_SMM_BOOL_OP (mx_el_or, ||, M1, M2, LHS_ZERO, RHS_ZERO) \ + +#define SPARSE_SMM_BOOL_OPS(M1, M2, ZERO) \ + SPARSE_SMM_BOOL_OPS2(M1, M2, ZERO, ZERO) + +#define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2) \ + SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2) \ + SPARSE_SMM_CMP_OP_DECLS (M1, M2) \ + SPARSE_SMM_BOOL_OP_DECLS (M1, M2) + +// Avoid some code duplication. Maybe we should use templates. + +#define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN) \ + \ + int nr = rows (); \ + int nc = cols (); \ + \ + RET_TYPE retval; \ + \ + if (nr > 0 && nc > 0) \ + { \ + if ((nr == 1 && dim == -1) || dim == 1) \ + /* Ugly!! Is there a better way? */ \ + retval = transpose (). FCN (0) .transpose (); \ + else \ + { \ + int nel = 0; \ + for (int i = 0; i < nc; i++) \ + { \ + ELT_TYPE t = ELT_TYPE (); \ + for (int j = cidx (i); j < cidx (i+1); j++) \ + { \ + t += data(j); \ + if (t != ELT_TYPE ()) \ + if (j == cidx(i+1) - 1) \ + nel += nr - ridx(j); \ + else \ + nel += ridx(j+1) - ridx(j); \ + } \ + } \ + retval = RET_TYPE (nr, nc, nel); \ + retval.cidx(0) = 0; \ + int ii = 0; \ + for (int i = 0; i < nc; i++) \ + { \ + ELT_TYPE t = ELT_TYPE (); \ + for (int j = cidx (i); j < cidx (i+1); j++) \ + { \ + t += data(j); \ + if (t != ELT_TYPE ()) \ + { \ + if (j == cidx(i+1) - 1) \ + { \ + for (int k = ridx(j); k < nr; k++) \ + { \ + retval.data (ii) = t; \ + retval.ridx (ii++) = k; \ + } \ + } \ + else \ + { \ + for (int k = ridx(j); k < ridx(j+1); k++) \ + { \ + retval.data (ii) = t; \ + retval.ridx (ii++) = k; \ + } \ + } \ + } \ + } \ + retval.cidx(i+1) = ii; \ + } \ + } \ + } \ + else \ + retval = RET_TYPE (nr,nc); \ + \ + return retval + + +#define SPARSE_CUMPROD(RET_TYPE, ELT_TYPE, FCN) \ + \ + int nr = rows (); \ + int nc = cols (); \ + \ + RET_TYPE retval; \ + \ + if (nr > 0 && nc > 0) \ + { \ + if ((nr == 1 && dim == -1) || dim == 1) \ + /* Ugly!! Is there a better way? */ \ + retval = transpose (). FCN (0) .transpose (); \ + else \ + { \ + int nel = 0; \ + for (int i = 0; i < nc; i++) \ + { \ + int jj = 0; \ + for (int j = cidx (i); j < cidx (i+1); j++) \ + { \ + if (jj == ridx(j)) \ + { \ + nel++; \ + jj++; \ + } \ + else \ + break; \ + } \ + } \ + retval = RET_TYPE (nr, nc, nel); \ + retval.cidx(0) = 0; \ + int ii = 0; \ + for (int i = 0; i < nc; i++) \ + { \ + ELT_TYPE t = ELT_TYPE (1.); \ + int jj = 0; \ + for (int j = cidx (i); j < cidx (i+1); j++) \ + { \ + if (jj == ridx(j)) \ + { \ + t *= data(j); \ + retval.data(ii) = t; \ + retval.ridx(ii++) = jj++; \ + } \ + else \ + break; \ + } \ + retval.cidx(i+1) = ii; \ + } \ + } \ + } \ + else \ + retval = RET_TYPE (nr,nc); \ + \ + return retval + +#define SPARSE_BASE_REDUCTION_OP(RET_TYPE, EL_TYPE, ROW_EXPR, COL_EXPR, \ + INIT_VAL, MT_RESULT) \ + \ + int nr = rows (); \ + int nc = cols (); \ + \ + RET_TYPE retval; \ + \ + if (nr > 0 && nc > 0) \ + { \ + if ((nr == 1 && dim == -1) || dim == 1) \ + { \ + OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nr); \ + \ + for (int i = 0; i < nr; i++) \ + { \ + tmp[i] = INIT_VAL; \ + for (int j = 0; j < nc; j++) \ + { \ + ROW_EXPR; \ + } \ + } \ + int nel = 0; \ + for (int i = 0; i < nr; i++) \ + if (tmp[i] != EL_TYPE ()) \ + nel++ ; \ + retval = RET_TYPE (nr, 1, nel); \ + retval.cidx(0) = 0; \ + retval.cidx(1) = nel; \ + nel = 0; \ + for (int i = 0; i < nr; i++) \ + if (tmp[i] != EL_TYPE ()) \ + { \ + retval.data(nel) = tmp[i]; \ + retval.ridx(nel++) = i; \ + } \ + } \ + else \ + { \ + OCTAVE_LOCAL_BUFFER (EL_TYPE, tmp, nc); \ + \ + for (int j = 0; j < nc; j++) \ + { \ + tmp[j] = INIT_VAL; \ + for (int i = 0; i < nr; i++) \ + { \ + COL_EXPR; \ + } \ + } \ + int nel = 0; \ + for (int i = 0; i < nc; i++) \ + if (tmp[i] != EL_TYPE ()) \ + nel++ ; \ + retval = RET_TYPE (1, nc, nel); \ + retval.cidx(0) = 0; \ + nel = 0; \ + for (int i = 0; i < nc; i++) \ + if (tmp[i] != EL_TYPE ()) \ + { \ + retval.data(nel) = tmp[i]; \ + retval.ridx(nel++) = 0; \ + retval.cidx(i+1) = retval.cidx(i) + 1; \ + } \ + else \ + retval.cidx(i+1) = retval.cidx(i); \ + } \ + } \ + else if (nc == 0 && (nr == 0 || (nr == 1 && dim == -1))) \ + { \ + retval = RET_TYPE (1, 1, 1); \ + retval.cidx(0) = 0; \ + retval.cidx(1) = 1; \ + retval.ridx(0) = 0; \ + retval.data(0) = MT_RESULT; \ + } \ + else if (nr == 0 && (dim == 0 || dim == -1)) \ + { \ + retval = RET_TYPE (1, nc, nc); \ + retval.cidx (0) = 0; \ + for (int i = 0; i < nc ; i++) \ + { \ + retval.ridx (i) = 0; \ + retval.cidx (i+1) = i; \ + retval.data (i) = MT_RESULT; \ + } \ + } \ + else if (nc == 0 && dim == 1) \ + { \ + retval = RET_TYPE (nr, 1, nr); \ + retval.cidx(0) = 0; \ + retval.cidx(1) = nr; \ + for (int i = 0; i < nr; i++) \ + { \ + retval.ridx(i) = i; \ + retval.data(i) = MT_RESULT; \ + } \ + } \ + else \ + retval.resize (nr > 0, nc > 0); \ + \ + return retval + +#define SPARSE_REDUCTION_OP_ROW_EXPR(OP) \ + tmp[i] OP elem (i, j) + +#define SPARSE_REDUCTION_OP_COL_EXPR(OP) \ + tmp[j] OP elem (i, j) + +#define SPARSE_REDUCTION_OP(RET_TYPE, EL_TYPE, OP, INIT_VAL, MT_RESULT) \ + SPARSE_BASE_REDUCTION_OP (RET_TYPE, EL_TYPE, \ + SPARSE_REDUCTION_OP_ROW_EXPR (OP), \ + SPARSE_REDUCTION_OP_COL_EXPR (OP), \ + INIT_VAL, MT_RESULT) + +#define SPARSE_ANY_ALL_OP_ROW_CODE(TEST_OP, TEST_TRUE_VAL) \ + if (elem (i, j) TEST_OP 0.0) \ + { \ + tmp[i] = TEST_TRUE_VAL; \ + break; \ + } + +#define SPARSE_ANY_ALL_OP_COL_CODE(TEST_OP, TEST_TRUE_VAL) \ + if (elem (i, j) TEST_OP 0.0) \ + { \ + tmp[j] = TEST_TRUE_VAL; \ + break; \ + } + +#define SPARSE_ANY_ALL_OP(DIM, INIT_VAL, TEST_OP, TEST_TRUE_VAL) \ + SPARSE_BASE_REDUCTION_OP (SparseBoolMatrix, char, \ + SPARSE_ANY_ALL_OP_ROW_CODE (TEST_OP, TEST_TRUE_VAL), \ + SPARSE_ANY_ALL_OP_COL_CODE (TEST_OP, TEST_TRUE_VAL), \ + INIT_VAL, INIT_VAL) + +#define SPARSE_ALL_OP(DIM) SPARSE_ANY_ALL_OP (DIM, true, ==, false) + +#define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, !=, true) + +#define SPARSE_SPARSE_MUL( RET_TYPE, EL_TYPE ) \ + int nr = m.rows (); \ + int nc = m.cols (); \ + \ + int a_nr = a.rows (); \ + int a_nc = a.cols (); \ + \ + if (nc != a_nr) \ + { \ + gripe_nonconformant ("operator *", nr, nc, a_nr, a_nc); \ + return RET_TYPE (); \ + } \ + else \ + { \ + OCTAVE_LOCAL_BUFFER (EL_TYPE, Xcol, nr); \ + \ + int nel = 0; \ + \ + for (int i = 0; i < a_nc; i++) \ + { \ + OCTAVE_QUIT; \ + for (int k = 0; k < nr; k++) \ + Xcol[k]= 0.; \ + for (int j = a.cidx(i); j < a.cidx(i+1); j++) \ + { \ + int col = a.ridx(j); \ + for (int k = m.cidx(col) ; k < m.cidx(col+1); k++) \ + if (Xcol[m.ridx(k)] == 0.) \ + { \ + Xcol[m.ridx(k)] = 1.; \ + nel++; \ + } \ + } \ + } \ + \ + if (nel == 0) \ + return RET_TYPE (nr, a_nc); \ + else \ + { \ + RET_TYPE retval (nr, a_nc, nel); \ + \ + int ii = 0; \ + \ + retval.cidx(0) = 0; \ + for (int i = 0; i < a_nc ; i++) \ + { \ + OCTAVE_QUIT; \ + for (int k = 0; k < nr; k++) \ + Xcol[k]= 0.; \ + for (int j = a.cidx(i); j < a.cidx(i+1); j++) \ + { \ + int col = a.ridx(j); \ + EL_TYPE tmpval = a.data(j); \ + for (int k = m.cidx(col) ; k < m.cidx(col+1); k++) \ + Xcol[m.ridx(k)] += tmpval * m.data(k); \ + } \ + for (int k = 0; k < nr; k++) \ + { \ + if (Xcol[k] !=0. ) \ + { \ + retval.ridx (ii) = k; \ + retval.data (ii++) = Xcol[k]; \ + } \ + } \ + retval.cidx(i+1) = ii; \ + } \ + return retval; \ + } \ + } + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Sparse.cc b/liboctave/Sparse.cc new file mode 100644 --- /dev/null +++ b/liboctave/Sparse.cc @@ -0,0 +1,2834 @@ +// Template sparse array class +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "Array.h" +#include "Array-flags.h" +#include "Array-util.h" +#include "Range.h" +#include "idx-vector.h" +#include "lo-error.h" +#include "lo-sstream.h" +#include "quit.h" + +#include "Sparse.h" +#include "sparse-sort.h" +#include "oct-spparms.h" + +template +T& +Sparse::SparseRep::elem (int _r, int _c) +{ + int i; + + if (nnz > 0) + { + for (i = c[_c]; i < c[_c + 1]; i++) + if (r[i] == _r) + return d[i]; + else if (r[i] > _r) + break; + + // Ok, If we've gotten here, we're in trouble.. Have to create a + // new element in the sparse array. This' gonna be slow!!! + if (c[ncols+1] == nnz) + { + (*current_liboctave_error_handler) + ("Sparse::SparseRep::elem (int, int): sparse matrix filled"); + return *d; + } + + int to_move = c[ncols] - i; + if (to_move != 0) + { + for (int j = c[ncols]; j > i; j--) + { + d[j] = d[j-1]; + r[j] = r[j-1]; + } + } + + for (int j = _c + 1; j < ncols + 1; j++) + c[j] = c[j] + 1; + + d[i] = 0.; + r[i] = _r; + + return d[i]; + } + else + { + (*current_liboctave_error_handler) + ("Sparse::SparseRep::elem (int, int): sparse matrix filled"); + return *d; + } +} + +template +T +Sparse::SparseRep::celem (int _r, int _c) const +{ + if (nnz > 0) + for (int i = c[_c]; i < c[_c + 1]; i++) + if (r[i] == _r) + return d[i]; + return T (); +} + +template +void +Sparse::SparseRep::maybe_compress (bool remove_zeros) +{ + int ndel = nnz - c[ncols]; + int nzero = 0; + + if (remove_zeros) + for (int i = 0; i < nnz - ndel; i++) + if (d[i] == T ()) + nzero++; + + if (!ndel && !nzero) + return; + + if (!nzero) + { + int new_nnz = nnz - ndel; + + T *new_data = new T [new_nnz]; + for (int i = 0; i < new_nnz; i++) + new_data[i] = d[i]; + delete [] d; + d = new_data; + + int *new_ridx = new int [new_nnz]; + for (int i = 0; i < new_nnz; i++) + new_ridx[i] = r[i]; + delete [] r; + r = new_ridx; + } + else + { + int new_nnz = nnz - ndel - nzero; + + T *new_data = new T [new_nnz]; + int *new_ridx = new int [new_nnz]; + + int ii = 0; + int ic = 0; + for (int j = 0; j < ncols; j++) + { + for (int k = ic; k < c[j+1]; k++) + if (d[k] != T ()) + { + new_data [ii] = d[k]; + new_ridx [ii++] = r[k]; + } + ic = c[j+1]; + c[j+1] = ii; + } + + delete [] d; + d = new_data; + + delete [] r; + r = new_ridx; + } + + nnz -= ndel + nzero; +} + +template +void +Sparse::SparseRep::change_length (int nz) +{ + if (nz != nnz) + { + int min_nnz = (nz < nnz ? nz : nnz); + + int * new_ridx = new int [nz]; + for (int i = 0; i < min_nnz; i++) + new_ridx[i] = r[i]; + + delete [] r; + r = new_ridx; + + T * new_data = new T [nz]; + for (int i = 0; i < min_nnz; i++) + new_data[i] = d[i]; + + delete [] d; + d = new_data; + + if (nz < nnz) + for (int i = 0; i <= ncols; i++) + if (c[i] > nz) + c[i] = nz; + + nnz = nz; + } +} + +template +template +Sparse::Sparse (const Sparse& a) + : dimensions (a.dimensions), idx (0), idx_count (0) +{ + if (a.nnz () == 0) + rep = new typename Sparse::SparseRep (rows (), cols()); + else + { + rep = new typename Sparse::SparseRep (rows (), cols (), a.nnz ()); + + int nz = nnz (); + int nc = cols (); + for (int i = 0; i < nz; i++) + { + xdata (i) = T (a.data (i)); + xridx (i) = a.ridx (i); + } + for (int i = 0; i < nc + 1; i++) + xcidx (i) = a.cidx (i); + } +} + +template +Sparse::Sparse (int nr, int nc, T val) + : rep (new typename Sparse::SparseRep (nr, nc, nr*nc)), + dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) +{ + + int ii = 0; + xcidx (0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + xdata (ii) = val; + xridx (ii++) = i; + } + xcidx (j+1) = ii; + } +} + +template +Sparse::Sparse (const dim_vector& dv) + : dimensions (dv), idx (0), idx_count (0) +{ + if (dv.length() != 2) + (*current_liboctave_error_handler) + ("Sparse::Sparse (const dim_vector&): dimension mismatch"); + else + rep = new typename Sparse::SparseRep (dv(0), dv(1)); +} + +template +Sparse::Sparse (const Sparse& a, const dim_vector& dv) + : dimensions (dv), idx (0), idx_count (0) +{ + + // Work in unsigned long long to avoid overflow issues with numel + unsigned long long a_nel = static_cast(a.rows ()) * + static_cast(a.cols ()); + unsigned long long dv_nel = static_cast(dv (0)) * + static_cast(dv (1)); + + if (a_nel != dv_nel) + (*current_liboctave_error_handler) + ("Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch"); + else + { + dim_vector old_dims = a.dims(); + int new_nnz = a.nnz (); + int new_nr = dv (0); + int new_nc = dv (1); + int old_nr = old_dims (0); + int old_nc = old_dims (1); + + rep = new typename Sparse::SparseRep (new_nr, new_nc, new_nnz); + + int kk = 0; + xcidx(0) = 0; + for (int i = 0; i < old_nc; i++) + for (int j = a.cidx(i); j < a.cidx(i+1); j++) + { + int tmp = i * old_nr + a.ridx(j); + int ii = tmp % new_nr; + int jj = (tmp - ii) / new_nr; + for (int k = kk; k < jj; k++) + xcidx(k+1) = j; + kk = jj; + xdata(j) = a.data(j); + xridx(j) = ii; + } + for (int k = kk; k < new_nc; k++) + xcidx(k+1) = new_nnz; + } +} + +template +Sparse::Sparse (const Array& a, const Array& r, + const Array& c, int nr, + int nc, bool sum_terms) + : dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) +{ + int a_len = a.length (); + int r_len = r.length (); + int c_len = c.length (); + bool ri_scalar = (r_len == 1); + bool ci_scalar = (c_len == 1); + bool cf_scalar = (a_len == 1); + + if ((a_len != r_len && !cf_scalar && !ri_scalar) || + (a_len != c_len && !cf_scalar && !ci_scalar) || + (r_len != c_len && !ri_scalar && !ci_scalar) || nr < 0 || nc < 0) + { + (*current_liboctave_error_handler) + ("Sparse::Sparse (const Array&, const Array&, ...): dimension mismatch"); + rep = nil_rep (); + dimensions = dim_vector (0, 0); + } + else + { + int max_nnz = (r_len > c_len ? r_len : c_len); + + OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl *, sidx, max_nnz); + OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl, sidxX, max_nnz); + + for (int i = 0; i < max_nnz; i++) + sidx[i] = &sidxX[i]; + + int actual_nnz = 0; + OCTAVE_QUIT; + for (int i = 0; i < max_nnz; i++) + { + int rowidx = (ri_scalar ? r(0) : r(i)); + int colidx = (ci_scalar ? c(0) : c(i)); + if (rowidx < nr && rowidx >= 0 && + colidx < nc && colidx >= 0 ) + { + if ( a (cf_scalar ? 0 : i ) != T ()) + { + sidx[actual_nnz]->r = rowidx; + sidx[actual_nnz]->c = colidx; + sidx[actual_nnz]->idx = i; + actual_nnz++; + } + } + else + { + (*current_liboctave_error_handler) + ("Sparse::Sparse : index (%d,%d) out of range", + rowidx + 1, colidx + 1); + rep = nil_rep (); + dimensions = dim_vector (0, 0); + return; + } + } + + if (actual_nnz == 0) + rep = new typename Sparse::SparseRep (nr, nc); + else + { + OCTAVE_QUIT; + octave_sort + sort (octave_sparse_sidxl_comp); + + sort.sort (sidx, actual_nnz); + OCTAVE_QUIT; + + // Now count the unique non-zero values + int real_nnz = 1; + for (int i = 1; i < actual_nnz; i++) + if (sidx[i-1]->r != sidx[i]->r || sidx[i-1]->c != sidx[i]->c) + real_nnz++; + + rep = new typename Sparse::SparseRep (nr, nc, real_nnz); + + int cx = 0; + int prev_rval = -1; + int prev_cval = -1; + int ii = -1; + xcidx (0) = 0; + for (int i = 0; i < actual_nnz; i++) + { + OCTAVE_QUIT; + int iidx = sidx[i]->idx; + int rval = sidx[i]->r; + int cval = sidx[i]->c; + + if (prev_cval < cval || (prev_rval < rval && prev_cval == cval)) + { + int ci = static_cast (c (ci_scalar ? 0 : iidx)); + ii++; + while (cx < ci) + xcidx (++cx) = ii; + xdata(ii) = a (cf_scalar ? 0 : iidx); + xridx(ii) = static_cast (r (ri_scalar ? 0 : iidx)); + } + else + { + if (sum_terms) + xdata(ii) += a (cf_scalar ? 0 : iidx); + else + xdata(ii) = a (cf_scalar ? 0 : iidx); + } + prev_rval = rval; + prev_cval = cval; + } + + while (cx < nc) + xcidx (++cx) = ii + 1; + } + } +} + +template +Sparse::Sparse (const Array& a, const Array& r, + const Array& c, int nr, + int nc, bool sum_terms) + : dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) +{ + int a_len = a.length (); + int r_len = r.length (); + int c_len = c.length (); + bool ri_scalar = (r_len == 1); + bool ci_scalar = (c_len == 1); + bool cf_scalar = (a_len == 1); + + if ((a_len != r_len && !cf_scalar && !ri_scalar) || + (a_len != c_len && !cf_scalar && !ci_scalar) || + (r_len != c_len && !ri_scalar && !ci_scalar) || nr < 0 || nc < 0) + { + (*current_liboctave_error_handler) + ("Sparse::Sparse (const Array&, const Array&, ...): dimension mismatch"); + rep = nil_rep (); + dimensions = dim_vector (0, 0); + } + else + { + int max_nnz = (r_len > c_len ? r_len : c_len); + + OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl *, sidx, max_nnz); + OCTAVE_LOCAL_BUFFER (octave_sparse_sort_idxl, sidxX, max_nnz); + + for (int i = 0; i < max_nnz; i++) + sidx[i] = &sidxX[i]; + + int actual_nnz = 0; + OCTAVE_QUIT; + + for (int i = 0; i < max_nnz; i++) + { + int rowidx = static_cast (ri_scalar ? r(0) : r(i)); + int colidx = static_cast (ci_scalar ? c(0) : c(i)); + if (rowidx < nr && rowidx >= 0 && + colidx < nc && colidx >= 0 ) + { + if ( a (cf_scalar ? 0 : i ) != T ()) + { + sidx[actual_nnz]->r = rowidx; + sidx[actual_nnz]->c = colidx; + sidx[actual_nnz]->idx = i; + actual_nnz++; + } + } + else + { + (*current_liboctave_error_handler) + ("Sparse::Sparse : index (%d,%d) out of range", + rowidx + 1, colidx + 1); + rep = nil_rep (); + dimensions = dim_vector (0, 0); + return; + } + } + + if (actual_nnz == 0) + rep = new typename Sparse::SparseRep (nr, nc); + else + { + OCTAVE_QUIT; + octave_sort + sort (octave_sparse_sidxl_comp); + + sort.sort (sidx, actual_nnz); + OCTAVE_QUIT; + + // Now count the unique non-zero values + int real_nnz = 1; + for (int i = 1; i < actual_nnz; i++) + if (sidx[i-1]->r != sidx[i]->r || sidx[i-1]->c != sidx[i]->c) + real_nnz++; + + rep = new typename Sparse::SparseRep (nr, nc, real_nnz); + + int cx = 0; + int prev_rval = -1; + int prev_cval = -1; + int ii = -1; + xcidx (0) = 0; + for (int i = 0; i < actual_nnz; i++) + { + OCTAVE_QUIT; + int iidx = sidx[i]->idx; + int rval = sidx[i]->r; + int cval = sidx[i]->c; + + if (prev_cval < cval || (prev_rval < rval && prev_cval == cval)) + { + int ci = static_cast (c (ci_scalar ? 0 : iidx)); + ii++; + + while (cx < ci) + xcidx (++cx) = ii; + xdata(ii) = a (cf_scalar ? 0 : iidx); + xridx(ii) = static_cast (r (ri_scalar ? 0 : iidx)); + } + else + { + if (sum_terms) + xdata(ii) += a (cf_scalar ? 0 : iidx); + else + xdata(ii) = a (cf_scalar ? 0 : iidx); + } + prev_rval = rval; + prev_cval = cval; + } + + while (cx < nc) + xcidx (++cx) = ii + 1; + } + } +} + +template +Sparse::Sparse (const Array2& a) + : dimensions (a.dims ()), idx (0), idx_count (0) +{ + int nr = rows (); + int nc = cols (); + int len = a.length (); + int new_nnz = 0; + + // First count the number of non-zero terms + for (int i = 0; i < len; i++) + if (a(i) != T ()) + new_nnz++; + + rep = new typename Sparse::SparseRep (nr, nc, new_nnz); + + int ii = 0; + xcidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + if (a.elem (i,j) != T ()) + { + xdata(ii) = a.elem (i,j); + xridx(ii++) = i; + } + xcidx(j+1) = ii; + } +} + +template +Sparse::Sparse (const Array& a) + : dimensions (a.dims ()), idx (0), idx_count (0) +{ + if (dimensions.length () > 2) + (*current_liboctave_error_handler) + ("Sparse::Sparse (const Array&): dimension mismatch"); + else + { + int nr = rows (); + int nc = cols (); + int len = a.length (); + int new_nnz = 0; + + // First count the number of non-zero terms + for (int i = 0; i < len; i++) + if (a(i) != T ()) + new_nnz++; + + rep = new typename Sparse::SparseRep (nr, nc, new_nnz); + + int ii = 0; + xcidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + if (a.elem (i,j) != T ()) + { + xdata(ii) = a.elem (i,j); + xridx(ii++) = i; + } + xcidx(j+1) = ii; + } + } +} + +template +Sparse::~Sparse (void) +{ + if (--rep->count <= 0) + delete rep; + + delete [] idx; +} + +template +int +Sparse::compute_index (const Array& ra_idx) const +{ + int retval = -1; + + int n = dimensions.length (); + + if (n > 0 && n == ra_idx.length ()) + { + retval = ra_idx(--n); + + while (--n >= 0) + { + retval *= dimensions(n); + retval += ra_idx(n); + } + } + else + (*current_liboctave_error_handler) + ("Sparse::compute_index: invalid ra_idxing operation"); + + return retval; +} + +template +T +Sparse::range_error (const char *fcn, int n) const +{ + (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); + return T (); +} + +template +T& +Sparse::range_error (const char *fcn, int n) +{ + (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); + static T foo; + return foo; +} + +template +T +Sparse::range_error (const char *fcn, int i, int j) const +{ + (*current_liboctave_error_handler) + ("%s (%d, %d): range error", fcn, i, j); + return T (); +} + +template +T& +Sparse::range_error (const char *fcn, int i, int j) +{ + (*current_liboctave_error_handler) + ("%s (%d, %d): range error", fcn, i, j); + static T foo; + return foo; +} + +template +T +Sparse::range_error (const char *fcn, const Array& ra_idx) const +{ + OSSTREAM buf; + + buf << fcn << " ("; + + int n = ra_idx.length (); + + if (n > 0) + buf << ra_idx(0); + + for (int i = 1; i < n; i++) + buf << ", " << ra_idx(i); + + buf << "): range error"; + + buf << OSSTREAM_ENDS; + + (*current_liboctave_error_handler) (OSSTREAM_C_STR (buf)); + + OSSTREAM_FREEZE (buf); + + return T (); +} + +template +T& +Sparse::range_error (const char *fcn, const Array& ra_idx) +{ + OSSTREAM buf; + + buf << fcn << " ("; + + int n = ra_idx.length (); + + if (n > 0) + buf << ra_idx(0); + + for (int i = 1; i < n; i++) + buf << ", " << ra_idx(i); + + buf << "): range error"; + + buf << OSSTREAM_ENDS; + + (*current_liboctave_error_handler) (OSSTREAM_C_STR (buf)); + + OSSTREAM_FREEZE (buf); + + static T foo; + return foo; +} + +template +Sparse +Sparse::reshape (const dim_vector& new_dims) const +{ + Sparse retval; + + if (dimensions != new_dims) + { + if (dimensions.numel () == new_dims.numel ()) + { + int new_nnz = nnz (); + int new_nr = new_dims (0); + int new_nc = new_dims (1); + int old_nr = rows (); + int old_nc = cols (); + retval = Sparse (new_nr, new_nc, new_nnz); + + int kk = 0; + retval.xcidx(0) = 0; + for (int i = 0; i < old_nc; i++) + for (int j = cidx(i); j < cidx(i+1); j++) + { + int tmp = i * old_nr + ridx(j); + int ii = tmp % new_nr; + int jj = (tmp - ii) / new_nr; + for (int k = kk; k < jj; k++) + retval.xcidx(k+1) = j; + kk = jj; + retval.xdata(j) = data(j); + retval.xridx(j) = ii; + } + retval.xcidx(new_nc) = new_nnz; + } + else + (*current_liboctave_error_handler) ("reshape: size mismatch"); + } + else + retval = *this; + + return retval; +} + +template +Sparse +Sparse::permute (const Array& perm_vec, bool) const +{ + dim_vector dv = dims (); + dim_vector dv_new; + + int nd = dv.length (); + + dv_new.resize (nd); + + // Need this array to check for identical elements in permutation array. + Array checked (nd, false); + + // Find dimension vector of permuted array. + for (int i = 0; i < nd; i++) + { + int perm_el = perm_vec.elem (i); + + if (perm_el > dv.length () || perm_el < 1) + { + (*current_liboctave_error_handler) + ("permutation vector contains an invalid element"); + + return Sparse (); + } + + if (checked.elem(perm_el - 1)) + { + (*current_liboctave_error_handler) + ("PERM cannot contain identical elements"); + + return Sparse (); + } + else + checked.elem(perm_el - 1) = true; + + dv_new (i) = dv (perm_el - 1); + } + + if (dv_new == dv) + return *this; + else + return transpose (); +} + +template +void +Sparse::resize_no_fill (const dim_vector& dv) +{ + int n = dv.length (); + + if (n != 2) + { + (*current_liboctave_error_handler) ("sparse array must be 2-D"); + return; + } + + resize_no_fill (dv(0), dv(1)); +} + +template +void +Sparse::resize_no_fill (int r, int c) +{ + if (r < 0 || c < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (ndims () == 0) + dimensions = dim_vector (0, 0); + + if (r == dim1 () && c == dim2 ()) + return; + + typename Sparse::SparseRep *old_rep = Sparse::rep; + int nc = cols (); + int nr = rows (); + + if (nnz () == 0 || r == 0 || c == 0) + // Special case of redimensioning to/from a sparse matrix with + // no elements + rep = new typename Sparse::SparseRep (r, c); + else + { + int n = 0; + Sparse tmpval; + if (r >= nr) + { + if (c > nc) + n = cidx(nc); + else + n = cidx(c); + + tmpval = Sparse (r, c, n); + + if (c > nc) + { + for (int i = 0; i < nc; i++) + tmpval.cidx(i) = cidx(i); + for (int i = nc+2; i < c; i++) + tmpval.cidx(i) = tmpval.cidx(i-1); + } + else if (c <= nc) + for (int i = 0; i < c; i++) + tmpval.cidx(i) = cidx(i); + + for (int i = 0; i < n; i++) + { + tmpval.data(i) = data(i); + tmpval.ridx(i) = ridx(i); + } + } + else + { + // Count how many non zero terms before we do anything + for (int i = 0; i < c; i++) + for (int j = cidx(i); j < cidx(i+1); j++) + if (ridx(j) < r) + n++; + + if (n) + { + // Now that we know the size we can do something + tmpval = Sparse (r, c, n); + + tmpval.cidx(0); + for (int i = 0, ii = 0; i < c; i++) + { + for (int j = cidx(i); j < cidx(i+1); j++) + if (ridx(j) < r) + { + tmpval.data(ii) = data(j); + tmpval.ridx(ii++) = ridx(j); + } + tmpval.cidx(i+1) = ii; + } + } + else + tmpval = Sparse (r, c); + } + + rep = tmpval.rep; + rep->count++; + } + + dimensions = dim_vector (r, c); + + if (--old_rep->count <= 0) + delete old_rep; +} + +template +Sparse& +Sparse::insert (const Sparse& a, int r, int c) +{ + int a_rows = a.rows (); + int a_cols = a.cols (); + int nr = rows (); + int nc = cols (); + + if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) + { + (*current_liboctave_error_handler) ("range error for insert"); + return *this; + } + + // First count the number of elements in the final array + int nel = cidx(c) + a.nnz (); + + if (c + a_cols < nc) + nel += cidx(nc) - cidx(c + a_cols); + + for (int i = c; i < c + a_cols; i++) + for (int j = cidx(i); j < cidx(i+1); j++) + if (ridx(j) < r || ridx(j) >= r + a_rows) + nel++; + + Sparse tmp (*this); + --rep->count; + rep = new typename Sparse::SparseRep (nr, nc, nel); + + for (int i = 0; i < tmp.cidx(c); i++) + { + data(i) = tmp.data(i); + ridx(i) = tmp.ridx(i); + } + for (int i = 0; i < c + 1; i++) + cidx(i) = tmp.cidx(i); + + int ii = cidx(c); + + for (int i = c; i < c + a_cols; i++) + { + OCTAVE_QUIT; + + for (int j = tmp.cidx(i); j < tmp.cidx(i+1); j++) + if (tmp.ridx(j) < r) + { + data(ii) = tmp.data(j); + ridx(ii++) = tmp.ridx(j); + } + + OCTAVE_QUIT; + + for (int j = a.cidx(i-c); j < a.cidx(i-c+1); j++) + { + data(ii) = a.data(j); + ridx(ii++) = r + a.ridx(j); + } + + OCTAVE_QUIT; + + for (int j = tmp.cidx(i); j < tmp.cidx(i+1); j++) + if (tmp.ridx(j) >= r + a_rows) + { + data(ii) = tmp.data(j); + ridx(ii++) = tmp.ridx(j); + } + + cidx(i+1) = ii; + } + + for (int i = c + a_cols; i < nc; i++) + { + for (int j = tmp.cidx(i); j < tmp.cidx(i+1); j++) + { + data(ii) = tmp.data(j); + ridx(ii++) = tmp.ridx(j); + } + cidx(i+1) = ii; + } + + return *this; +} + +template +Sparse& +Sparse::insert (const Sparse& a, const Array& ra_idx) +{ + + if (ra_idx.length () != 2) + { + (*current_liboctave_error_handler) ("range error for insert"); + return *this; + } + + return insert (a, ra_idx (0), ra_idx (1)); +} + +template +Sparse +Sparse::transpose (void) const +{ + assert (ndims () == 2); + + int nr = rows (); + int nc = cols (); + int nz = nnz (); + Sparse retval (nc, nr, nz); + + retval.cidx(0) = 0; + for (int i = 0, iidx = 0; i < nr; i++) + { + for (int j = 0; j < nc; j++) + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + retval.data(iidx) = data(k); + retval.ridx(iidx++) = j; + } + retval.cidx(i+1) = iidx; + } + + return retval; +} + +template +void +Sparse::clear_index (void) +{ + delete [] idx; + idx = 0; + idx_count = 0; +} + +template +void +Sparse::set_index (const idx_vector& idx_arg) +{ + int nd = ndims (); + + if (! idx && nd > 0) + idx = new idx_vector [nd]; + + if (idx_count < nd) + { + idx[idx_count++] = idx_arg; + } + else + { + idx_vector *new_idx = new idx_vector [idx_count+1]; + + for (int i = 0; i < idx_count; i++) + new_idx[i] = idx[i]; + + new_idx[idx_count++] = idx_arg; + + delete [] idx; + + idx = new_idx; + } +} + +template +void +Sparse::maybe_delete_elements (idx_vector& idx_arg) +{ + int nr = dim1 (); + int nc = dim2 (); + + if (nr == 0 && nc == 0) + return; + + int n; + if (nr == 1) + n = nc; + else if (nc == 1) + n = nr; + else + { + // Reshape to row vector for Matlab compatibility. + + n = nr * nc; + nr = 1; + nc = n; + } + + if (idx_arg.is_colon_equiv (n, 1)) + { + // Either A(:) = [] or A(idx) = [] with idx enumerating all + // elements, so we delete all elements and return [](0x0). To + // preserve the orientation of the vector, you have to use + // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). + + resize_no_fill (0, 0); + return; + } + + idx_arg.sort (true); + + int num_to_delete = idx_arg.length (n); + + if (num_to_delete != 0) + { + int new_n = n; + int new_nnz = nnz (); + + int iidx = 0; + + const Sparse tmp (*this); + + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + if (i == idx_arg.elem (iidx)) + { + iidx++; + new_n--; + + if (tmp.elem (i) != T ()) + new_nnz--; + + if (iidx == num_to_delete) + break; + } + } + + if (new_n > 0) + { + rep->count--; + + if (nr == 1) + rep = new typename Sparse::SparseRep (1, new_n, new_nnz); + else + rep = new typename Sparse::SparseRep (new_n, 1, new_nnz); + + int ii = 0; + int jj = 0; + iidx = 0; + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + if (iidx < num_to_delete && i == idx_arg.elem (iidx)) + iidx++; + else + { + T el = tmp.elem (i); + if (el != T ()) + { + data(ii) = el; + ridx(ii++) = jj; + } + jj++; + } + } + + dimensions.resize (2); + + if (nr == 1) + { + ii = 0; + cidx(0) = 0; + for (int i = 0; i < new_n; i++) + { + OCTAVE_QUIT; + if (ridx(ii) == i) + ridx(ii++) = 0; + cidx(i+1) = ii; + } + + dimensions(0) = 1; + dimensions(1) = new_n; + } + else + { + cidx(0) = 0; + cidx(1) = new_nnz; + dimensions(0) = new_n; + dimensions(1) = 1; + } + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } +} + +template +void +Sparse::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j) +{ + assert (ndims () == 2); + + int nr = dim1 (); + int nc = dim2 (); + + if (nr == 0 && nc == 0) + return; + + if (idx_i.is_colon ()) + { + if (idx_j.is_colon ()) + { + // A(:,:) -- We are deleting columns and rows, so the result + // is [](0x0). + + resize_no_fill (0, 0); + return; + } + + if (idx_j.is_colon_equiv (nc, 1)) + { + // A(:,j) -- We are deleting columns by enumerating them, + // If we enumerate all of them, we should have zero columns + // with the same number of rows that we started with. + + resize_no_fill (nr, 0); + return; + } + } + + if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) + { + // A(i,:) -- We are deleting rows by enumerating them. If we + // enumerate all of them, we should have zero rows with the + // same number of columns that we started with. + + resize_no_fill (0, nc); + return; + } + + if (idx_i.is_colon_equiv (nr, 1)) + { + if (idx_j.is_colon_equiv (nc, 1)) + resize_no_fill (0, 0); + else + { + idx_j.sort (true); + + int num_to_delete = idx_j.length (nc); + + if (num_to_delete != 0) + { + if (nr == 1 && num_to_delete == nc) + resize_no_fill (0, 0); + else + { + int new_nc = nc; + int new_nnz = nnz (); + + int iidx = 0; + + for (int j = 0; j < nc; j++) + { + OCTAVE_QUIT; + + if (j == idx_j.elem (iidx)) + { + iidx++; + new_nc--; + + new_nnz -= cidx(j+1) - cidx(j); + + if (iidx == num_to_delete) + break; + } + } + + if (new_nc > 0) + { + const Sparse tmp (*this); + --rep->count; + rep = new typename Sparse::SparseRep (nr, new_nc, + new_nnz); + int ii = 0; + int jj = 0; + iidx = 0; + cidx(0) = 0; + for (int j = 0; j < nc; j++) + { + OCTAVE_QUIT; + + if (iidx < num_to_delete && j == idx_j.elem (iidx)) + iidx++; + else + { + for (int i = tmp.cidx(j); + i < tmp.cidx(j+1); i++) + { + data(jj) = tmp.data(i); + ridx(jj++) = tmp.ridx(i); + } + cidx(++ii) = jj; + } + } + + dimensions.resize (2); + dimensions(1) = new_nc; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } + } + } + } + else if (idx_j.is_colon_equiv (nc, 1)) + { + if (idx_i.is_colon_equiv (nr, 1)) + resize_no_fill (0, 0); + else + { + idx_i.sort (true); + + int num_to_delete = idx_i.length (nr); + + if (num_to_delete != 0) + { + if (nc == 1 && num_to_delete == nr) + resize_no_fill (0, 0); + else + { + int new_nr = nr; + int new_nnz = nnz (); + + int iidx = 0; + + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + + if (i == idx_i.elem (iidx)) + { + iidx++; + new_nr--; + + for (int j = 0; j < nnz (); j++) + if (ridx(j) == i) + new_nnz--; + + if (iidx == num_to_delete) + break; + } + } + + if (new_nr > 0) + { + const Sparse tmp (*this); + --rep->count; + rep = new typename Sparse::SparseRep (new_nr, nc, + new_nnz); + + int jj = 0; + cidx(0) = 0; + for (int i = 0; i < nc; i++) + { + iidx = 0; + for (int j = tmp.cidx(i); j < tmp.cidx(i+1); j++) + { + OCTAVE_QUIT; + + int ri = tmp.ridx(j); + + while (iidx < num_to_delete && + ri > idx_i.elem (iidx)) + { + iidx++; + } + + if (iidx == num_to_delete || + ri != idx_i.elem(iidx)) + { + data(jj) = tmp.data(j); + ridx(jj++) = ri - iidx; + } + } + cidx(i+1) = jj; + } + + dimensions.resize (2); + dimensions(0) = new_nr; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } + } + } + } +} + +template +void +Sparse::maybe_delete_elements (Array& ra_idx) +{ + if (ra_idx.length () == 1) + maybe_delete_elements (ra_idx(0)); + else if (ra_idx.length () == 2) + maybe_delete_elements (ra_idx(0), ra_idx(1)); + else + (*current_liboctave_error_handler) + ("range error for maybe_delete_elements"); +} + +template +Sparse +Sparse::value (void) +{ + Sparse retval; + + int n_idx = index_count (); + + if (n_idx == 2) + { + idx_vector *tmp = get_idx (); + + idx_vector idx_i = tmp[0]; + idx_vector idx_j = tmp[1]; + + retval = index (idx_i, idx_j); + } + else if (n_idx == 1) + { + retval = index (idx[0]); + } + else + (*current_liboctave_error_handler) + ("Sparse::value: invalid number of indices specified"); + + clear_index (); + + return retval; +} + +template +Sparse +Sparse::index (idx_vector& idx_arg, int resize_ok) const +{ + Sparse retval; + + assert (ndims () == 2); + + int nr = dim1 (); + int nc = dim2 (); + int nz = nnz (); + + int orig_len = nr * nc; + + dim_vector idx_orig_dims = idx_arg.orig_dimensions (); + + int idx_orig_rows = idx_arg.orig_rows (); + int idx_orig_columns = idx_arg.orig_columns (); + + if (idx_orig_dims.length () > 2) + (*current_liboctave_error_handler) + ("Sparse::index: Can not index Sparse with an N-D Array"); + else if (idx_arg.is_colon ()) + { + // Fast magic colon processing. + retval = Sparse (nr * nc, 1, nz); + + for (int i = 0; i < nc; i++) + for (int j = cidx(i); j < cidx(i+1); j++) + { + OCTAVE_QUIT; + retval.xdata(j) = data(j); + retval.xridx(j) = ridx(j) + i * nr; + } + retval.xcidx(0) = 0; + retval.xcidx(1) = nz; + } + else if (nr == 1 && nc == 1) + { + // You have to be pretty sick to get to this bit of code, + // since you have a scalar stored as a sparse matrix, and + // then want to make a dense matrix with sparse + // representation. Ok, we'll do it, but you deserve what + // you get!! + int n = idx_arg.freeze (length (), "sparse vector", resize_ok); + if (n == 0) + if (idx_arg.one_zero_only ()) + retval = Sparse (dim_vector (0, 0)); + else + retval = Sparse (dim_vector (0, 1)); + else if (nz < 1) + if (n >= idx_orig_dims.numel ()) + retval = Sparse (idx_orig_dims); + else + retval = Sparse (dim_vector (n, 1)); + else if (n >= idx_orig_dims.numel ()) + { + T el = elem (0); + int new_nr = idx_orig_rows; + int new_nc = idx_orig_columns; + for (int i = 2; i < idx_orig_dims.length (); i++) + new_nc *= idx_orig_dims (i); + + retval = Sparse (new_nr, new_nc, idx_arg.ones_count ()); + + int ic = 0; + for (int i = 0; i < n; i++) + { + if (i % new_nr == 0) + retval.xcidx(i % new_nr) = ic; + + int ii = idx_arg.elem (i); + if (ii == 0) + { + OCTAVE_QUIT; + retval.xdata(ic) = el; + retval.xridx(ic++) = i % new_nr; + } + } + retval.xcidx (new_nc) = ic; + } + else + { + T el = elem (0); + retval = Sparse (n, 1, nz); + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + retval.xdata(i) = el; + retval.xridx(i) = i; + } + retval.xcidx(0) = 0; + retval.xcidx(1) = n; + } + } + else if (nr == 1 || nc == 1) + { + // If indexing a vector with a matrix, return value has same + // shape as the index. Otherwise, it has same orientation as + // indexed object. + int len = length (); + int n = idx_arg.freeze (len, "sparse vector", resize_ok); + + if (n == 0) + if (nr == 1) + retval = Sparse (dim_vector (1, 0)); + else + retval = Sparse (dim_vector (0, 1)); + else if (nz < 1) + if ((n != 0 && idx_arg.one_zero_only ()) + || idx_orig_rows == 1 || idx_orig_columns == 1) + retval = Sparse ((nr == 1 ? 1 : n), (nr == 1 ? n : 1)); + else + retval = Sparse (idx_orig_dims); + else + { + + int new_nnz = 0; + if (nr == 1) + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_arg.elem (i); + if (ii < len) + if (cidx(ii) != cidx(ii+1)) + new_nnz++; + } + else + for (int i = 0; i < n; i++) + { + int ii = idx_arg.elem (i); + if (ii < len) + for (int j = 0; j < nz; j++) + { + OCTAVE_QUIT; + + if (ridx(j) == ii) + new_nnz++; + if (ridx(j) >= ii) + break; + } + } + + if (idx_arg.one_zero_only () || idx_orig_rows == 1 || + idx_orig_columns == 1) + { + if (nr == 1) + { + retval = Sparse (1, n, new_nnz); + int jj = 0; + retval.xcidx(0) = 0; + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_arg.elem (i); + if (ii < len) + if (cidx(ii) != cidx(ii+1)) + { + retval.xdata(jj) = data(cidx(ii)); + retval.xridx(jj++) = 0; + } + retval.xcidx(i+1) = jj; + } + } + else + { + retval = Sparse (n, 1, new_nnz); + retval.xcidx(0) = 0; + retval.xcidx(1) = new_nnz; + int jj = 0; + for (int i = 0; i < n; i++) + { + int ii = idx_arg.elem (i); + if (ii < len) + for (int j = 0; j < nz; j++) + { + OCTAVE_QUIT; + + if (ridx(j) == ii) + { + retval.xdata(jj) = data(j); + retval.xridx(jj++) = i; + } + if (ridx(j) >= ii) + break; + } + } + } + } + else + { + int new_nr; + int new_nc; + if (n >= idx_orig_dims.numel ()) + { + new_nr = idx_orig_rows; + new_nc = idx_orig_columns; + } + else + { + new_nr = n; + new_nc = 1; + } + + retval = Sparse (new_nr, new_nc, new_nnz); + + if (nr == 1) + { + int jj = 0; + retval.xcidx(0) = 0; + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_arg.elem (i); + if (ii < len) + if (cidx(ii) != cidx(ii+1)) + { + retval.xdata(jj) = data(cidx(ii)); + retval.xridx(jj++) = 0; + } + retval.xcidx(i/new_nr+1) = jj; + } + } + else + { + int jj = 0; + retval.xcidx(0) = 0; + for (int i = 0; i < n; i++) + { + int ii = idx_arg.elem (i); + if (ii < len) + for (int j = 0; j < nz; j++) + { + OCTAVE_QUIT; + + if (ridx(j) == ii) + { + retval.xdata(jj) = data(j); + retval.xridx(jj++) = i; + } + if (ridx(j) >= ii) + break; + } + retval.xcidx(i/new_nr+1) = jj; + } + } + } + } + } + else + { + if (liboctave_wfi_flag + && ! (idx_arg.one_zero_only () + && idx_orig_rows == nr + && idx_orig_columns == nc)) + (*current_liboctave_warning_handler) + ("single index used for sparse matrix"); + + // This code is only for indexing matrices. The vector + // cases are handled above. + + idx_arg.freeze (nr * nc, "matrix", resize_ok); + + if (idx_arg) + { + int result_nr = idx_orig_rows; + int result_nc = idx_orig_columns; + + if (idx_arg.one_zero_only ()) + { + result_nr = idx_arg.ones_count (); + result_nc = (result_nr > 0 ? 1 : 0); + } + + if (nz < 1) + retval = Sparse (result_nr, result_nc); + else + { + // Count number of non-zero elements + int new_nnz = 0; + int kk = 0; + for (int j = 0; j < result_nc; j++) + { + for (int i = 0; i < result_nr; i++) + { + OCTAVE_QUIT; + + int ii = idx_arg.elem (kk++); + if (ii < orig_len) + { + int fr = ii % nr; + int fc = (ii - fr) / nr; + for (int k = cidx(fc); k < cidx(fc+1); k++) + { + if (ridx(k) == fr) + new_nnz++; + if (ridx(k) >= fr) + break; + } + } + } + } + + retval = Sparse (result_nr, result_nc, new_nnz); + + kk = 0; + int jj = 0; + retval.xcidx(0) = 0; + for (int j = 0; j < result_nc; j++) + { + for (int i = 0; i < result_nr; i++) + { + OCTAVE_QUIT; + + int ii = idx_arg.elem (kk++); + if (ii < orig_len) + { + int fr = ii % nr; + int fc = (ii - fr) / nr; + for (int k = cidx(fc); k < cidx(fc+1); k++) + { + if (ridx(k) == fr) + { + retval.xdata(jj) = data(k); + retval.xridx(jj++) = i; + } + if (ridx(k) >= fr) + break; + } + } + } + retval.xcidx(j+1) = jj; + } + } + // idx_vector::freeze() printed an error message for us. + } + } + + return retval; +} + +template +Sparse +Sparse::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok) const +{ + Sparse retval; + + assert (ndims () == 2); + + int nr = dim1 (); + int nc = dim2 (); + + int n = idx_i.freeze (nr, "row", resize_ok); + int m = idx_j.freeze (nc, "column", resize_ok); + + if (idx_i && idx_j) + { + if (idx_i.orig_empty () || idx_j.orig_empty () || n == 0 || m == 0) + { + retval.resize_no_fill (n, m); + } + else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc)) + { + retval = *this; + } + else + { + // First count the number of non-zero elements + int new_nnz = 0; + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_i.elem (i); + if (ii < nr && jj < nc) + { + for (int k = cidx(jj); k < cidx(jj+1); k++) + { + if (ridx(k) == ii) + new_nnz++; + if (ridx(k) >= ii) + break; + } + } + } + } + + retval = Sparse (n, m, new_nnz); + + int kk = 0; + retval.xcidx(0) = 0; + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_i.elem (i); + if (ii < nr && jj < nc) + { + for (int k = cidx(jj); k < cidx(jj+1); k++) + { + if (ridx(k) == ii) + { + retval.xdata(kk) = data(k); + retval.xridx(kk++) = i; + } + if (ridx(k) >= ii) + break; + } + } + } + retval.xcidx(j+1) = kk; + } + } + } + + // idx_vector::freeze() printed an error message for us. + + return retval; +} + +template +Sparse +Sparse::index (Array& ra_idx, int resize_ok) const +{ + + if (ra_idx.length () != 2) + { + (*current_liboctave_error_handler) ("range error for index"); + return *this; + } + + return index (ra_idx (0), ra_idx (1), resize_ok); +} + +// XXX FIXME XXX +// Unfortunately numel can overflow for very large but very sparse matrices. +// For now just flag an error when this happens. +template +int +assign1 (Sparse& lhs, const Sparse& rhs) +{ + int retval = 1; + + idx_vector *idx_tmp = lhs.get_idx (); + + idx_vector lhs_idx = idx_tmp[0]; + + int lhs_len = lhs.numel (); + int rhs_len = rhs.numel (); + + unsigned EIGHT_BYTE_INT long_lhs_len = + static_cast (lhs.rows ()) * + static_cast (lhs.cols ()); + + unsigned EIGHT_BYTE_INT long_rhs_len = + static_cast (rhs.rows ()) * + static_cast (rhs.cols ()); + + if (long_rhs_len != static_cast(rhs_len) || + long_lhs_len != static_cast(lhs_len)) + { + (*current_liboctave_error_handler) + ("A(I) = X: Matrix dimensions too large to ensure correct\n", + "operation. This is an limitation that should be removed\n", + "in the future."); + + lhs.clear_index (); + return 0; + } + + int nr = lhs.rows (); + int nc = lhs.cols (); + int nz = lhs.nnz (); + + int n = lhs_idx.freeze (lhs_len, "vector", true, liboctave_wrore_flag); + + if (n != 0) + { + int max_idx = lhs_idx.max () + 1; + max_idx = max_idx < lhs_len ? lhs_len : max_idx; + + // Take a constant copy of lhs. This means that elem won't + // create missing elements. + const Sparse c_lhs (lhs); + + if (rhs_len == n) + { + int new_nnz = lhs.nnz (); + + // First count the number of non-zero elements + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = lhs_idx.elem (i); + if (ii < lhs_len && c_lhs.elem(ii) != LT ()) + new_nnz--; + if (rhs.elem(i) != RT ()) + new_nnz++; + } + + if (nr > 1) + { + Sparse tmp (max_idx, 1, new_nnz); + tmp.cidx(0) = 0; + tmp.cidx(1) = tmp.nnz (); + + int i = 0; + int ii = 0; + if (i < nz) + ii = c_lhs.ridx(i); + + int j = 0; + int jj = lhs_idx.elem(j); + + int kk = 0; + + while (j < n || i < nz) + { + if (j == n || (i < nz && ii < jj)) + { + tmp.xdata (kk) = c_lhs.data (i); + tmp.xridx (kk++) = ii; + if (++i < nz) + ii = c_lhs.ridx(i); + } + else + { + RT rtmp = rhs.elem (j); + if (rtmp != RT ()) + { + tmp.xdata (kk) = rtmp; + tmp.xridx (kk++) = jj; + } + + if (ii == jj && i < nz) + if (++i < nz) + ii = c_lhs.ridx(i); + if (++j < n) + jj = lhs_idx.elem(j); + } + } + + lhs = tmp; + } + else + { + Sparse tmp (1, max_idx, new_nnz); + + int i = 0; + int ii = 0; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + + int j = 0; + int jj = lhs_idx.elem(j); + + int kk = 0; + int ic = 0; + + while (j < n || i < nz) + { + if (j == n || (i < nz && ii < jj)) + { + while (ic <= ii) + tmp.xcidx (ic++) = kk; + tmp.xdata (kk) = c_lhs.data (i); + i++; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + } + else + { + while (ic <= jj) + tmp.xcidx (ic++) = kk; + + RT rtmp = rhs.elem (j); + if (rtmp != RT ()) + tmp.xdata (kk) = rtmp; + if (ii == jj) + { + i++; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + } + j++; + if (j < n) + jj = lhs_idx.elem(j); + } + tmp.xridx (kk++) = 0; + } + + for (int iidx = ic; iidx < max_idx+1; iidx++) + tmp.xcidx(iidx) = kk; + + lhs = tmp; + } + } + else if (rhs_len == 1) + { + int new_nnz = lhs.nnz (); + RT scalar = rhs.elem (0); + bool scalar_non_zero = (scalar != RT ()); + + // First count the number of non-zero elements + if (scalar != RT ()) + new_nnz += n; + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = lhs_idx.elem (i); + if (ii < lhs_len && c_lhs.elem(ii) != LT ()) + new_nnz--; + } + + if (nr > 1) + { + Sparse tmp (max_idx, 1, new_nnz); + tmp.cidx(0) = 0; + tmp.cidx(1) = tmp.nnz (); + + int i = 0; + int ii = 0; + if (i < nz) + ii = c_lhs.ridx(i); + + int j = 0; + int jj = lhs_idx.elem(j); + + int kk = 0; + + while (j < n || i < nz) + { + if (j == n || (i < nz && ii < jj)) + { + tmp.xdata (kk) = c_lhs.data (i); + tmp.xridx (kk++) = ii; + if (++i < nz) + ii = c_lhs.ridx(i); + } + else + { + if (scalar_non_zero) + { + tmp.xdata (kk) = scalar; + tmp.xridx (kk++) = jj; + } + + if (ii == jj && i < nz) + if (++i < nz) + ii = c_lhs.ridx(i); + if (++j < n) + jj = lhs_idx.elem(j); + } + } + + lhs = tmp; + } + else + { + Sparse tmp (1, max_idx, new_nnz); + + int i = 0; + int ii = 0; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + + int j = 0; + int jj = lhs_idx.elem(j); + + int kk = 0; + int ic = 0; + + while (j < n || i < nz) + { + if (j == n || (i < nz && ii < jj)) + { + while (ic <= ii) + tmp.xcidx (ic++) = kk; + tmp.xdata (kk) = c_lhs.data (i); + i++; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + } + else + { + while (ic <= jj) + tmp.xcidx (ic++) = kk; + if (scalar_non_zero) + tmp.xdata (kk) = scalar; + if (ii == jj) + { + i++; + while (ii < nc && c_lhs.cidx(ii+1) <= i) + ii++; + } + j++; + if (j < n) + jj = lhs_idx.elem(j); + } + tmp.xridx (kk++) = 0; + } + + for (int iidx = ic; iidx < max_idx+1; iidx++) + tmp.xcidx(iidx) = kk; + + lhs = tmp; + } + } + else + { + (*current_liboctave_error_handler) + ("A(I) = X: X must be a scalar or a vector with same length as I"); + + retval = 0; + } + } + else if (lhs_idx.is_colon ()) + { + if (lhs_len == 0) + { + + int new_nnz = rhs.nnz (); + Sparse tmp (1, rhs_len, new_nnz); + + int ii = 0; + int jj = 0; + for (int i = 0; i < rhs.cols(); i++) + for (int j = rhs.cidx(i); j < rhs.cidx(i+1); j++) + { + OCTAVE_QUIT; + for (int k = jj; k <= i * rhs.rows() + rhs.ridx(j); k++) + tmp.cidx(jj++) = ii; + + tmp.data(ii) = rhs.data(j); + tmp.ridx(ii++) = 0; + } + + for (int i = jj; i < rhs_len + 1; i++) + tmp.cidx(i) = ii; + + lhs = tmp; + } + else + (*current_liboctave_error_handler) + ("A(:) = X: A must be the same size as X"); + } + else if (! (rhs_len == 1 || rhs_len == 0)) + { + (*current_liboctave_error_handler) + ("A([]) = X: X must also be an empty matrix or a scalar"); + + retval = 0; + } + + lhs.clear_index (); + + return retval; +} + +template +int +assign (Sparse& lhs, const Sparse& rhs) +{ + int retval = 1; + + int n_idx = lhs.index_count (); + + int lhs_nr = lhs.rows (); + int lhs_nc = lhs.cols (); + int lhs_nz = lhs.nnz (); + + int rhs_nr = rhs.rows (); + int rhs_nc = rhs.cols (); + + idx_vector *tmp = lhs.get_idx (); + + idx_vector idx_i; + idx_vector idx_j; + + if (n_idx > 2) + { + (*current_liboctave_error_handler) + ("A(I, J) = X: can only have 1 or 2 indexes for sparse matrices"); + return 0; + } + + if (n_idx > 1) + idx_j = tmp[1]; + + if (n_idx > 0) + idx_i = tmp[0]; + + if (n_idx == 2) + { + int n = idx_i.freeze (lhs_nr, "row", true, liboctave_wrore_flag); + idx_i.sort (true); + + int m = idx_j.freeze (lhs_nc, "column", true, liboctave_wrore_flag); + idx_j.sort (true); + + + int idx_i_is_colon = idx_i.is_colon (); + int idx_j_is_colon = idx_j.is_colon (); + + if (idx_i_is_colon) + n = lhs_nr > 0 ? lhs_nr : rhs_nr; + + if (idx_j_is_colon) + m = lhs_nc > 0 ? lhs_nc : rhs_nc; + + if (idx_i && idx_j) + { + if (rhs_nr == 0 && rhs_nc == 0) + { + lhs.maybe_delete_elements (idx_i, idx_j); + } + else + { + if (rhs_nr == 1 && rhs_nc == 1 && n >= 0 && m >= 0) + { + // No need to do anything if either of the indices + // are empty. + + if (n > 0 && m > 0) + { + int max_row_idx = idx_i_is_colon ? rhs_nr : + idx_i.max () + 1; + int max_col_idx = idx_j_is_colon ? rhs_nc : + idx_j.max () + 1; + int new_nr = max_row_idx > lhs_nr ? max_row_idx : + lhs_nr; + int new_nc = max_col_idx > lhs_nc ? max_col_idx : + lhs_nc; + RT scalar = rhs.elem (0, 0); + + // Count the number of non-zero terms + int new_nnz = lhs.nnz (); + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + if (jj < lhs_nc) + { + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + int ii = idx_i.elem (i); + + if (ii < lhs_nr) + { + for (int k = lhs.cidx(jj); + k < lhs.cidx(jj+1); k++) + { + if (lhs.ridx(k) == ii) + new_nnz--; + if (lhs.ridx(k) >= ii) + break; + } + } + } + } + } + + if (scalar != RT()) + new_nnz += m * n; + + Sparse stmp (new_nr, new_nc, new_nnz); + + int jji = 0; + int jj = idx_j.elem (jji); + int kk = 0; + stmp.cidx(0) = 0; + for (int j = 0; j < new_nc; j++) + { + if (jji < m && jj == j) + { + int iii = 0; + int ii = idx_i.elem (iii); + for (int i = 0; i < new_nr; i++) + { + OCTAVE_QUIT; + + if (iii < n && ii == i) + { + if (scalar != RT ()) + { + stmp.data(kk) = scalar; + stmp.ridx(kk++) = i; + } + if (++iii < n) + ii = idx_i.elem(iii); + } + else if (j < lhs.cols()) + { + for (int k = lhs.cidx(j); + k < lhs.cidx(j+1); k++) + { + if (lhs.ridx(k) == i) + { + stmp.data(kk) = lhs.data(k); + stmp.ridx(kk++) = i; + } + if (lhs.ridx(k) >= i) + break; + } + } + } + if (++jji < m) + jj = idx_j.elem(jji); + } + else if (j < lhs.cols()) + { + for (int i = lhs.cidx(j); + i < lhs.cidx(j+1); i++) + { + stmp.data(kk) = lhs.data(i); + stmp.ridx(kk++) = lhs.ridx(i); + } + } + stmp.cidx(j+1) = kk; + } + + lhs = stmp; + } + } + else if (n == rhs_nr && m == rhs_nc) + { + if (n > 0 && m > 0) + { + int max_row_idx = idx_i_is_colon ? rhs_nr : + idx_i.max () + 1; + int max_col_idx = idx_j_is_colon ? rhs_nc : + idx_j.max () + 1; + int new_nr = max_row_idx > lhs_nr ? max_row_idx : + lhs_nr; + int new_nc = max_col_idx > lhs_nc ? max_col_idx : + lhs_nc; + + // Count the number of non-zero terms + int new_nnz = lhs.nnz (); + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + OCTAVE_QUIT; + + if (jj < lhs_nc) + { + int ii = idx_i.elem (i); + + if (ii < lhs_nr) + { + for (int k = lhs.cidx(jj); + k < lhs.cidx(jj+1); k++) + { + if (lhs.ridx(k) == ii) + new_nnz--; + if (lhs.ridx(k) >= ii) + break; + } + } + } + + if (rhs.elem(i,j) != RT ()) + new_nnz++; + } + } + + Sparse stmp (new_nr, new_nc, new_nnz); + + int jji = 0; + int jj = idx_j.elem (jji); + int kk = 0; + stmp.cidx(0) = 0; + for (int j = 0; j < new_nc; j++) + { + if (jji < m && jj == j) + { + int iii = 0; + int ii = idx_i.elem (iii); + for (int i = 0; i < new_nr; i++) + { + OCTAVE_QUIT; + + if (iii < n && ii == i) + { + RT rtmp = rhs.elem (iii, jji); + if (rtmp != RT ()) + { + stmp.data(kk) = rtmp; + stmp.ridx(kk++) = i; + } + if (++iii < n) + ii = idx_i.elem(iii); + } + else if (j < lhs.cols()) + { + for (int k = lhs.cidx(j); + k < lhs.cidx(j+1); k++) + { + if (lhs.ridx(k) == i) + { + stmp.data(kk) = lhs.data(k); + stmp.ridx(kk++) = i; + } + if (lhs.ridx(k) >= i) + break; + } + } + } + if (++jji < m) + jj = idx_j.elem(jji); + } + else if (j < lhs.cols()) + { + for (int i = lhs.cidx(j); + i < lhs.cidx(j+1); i++) + { + stmp.data(kk) = lhs.data(i); + stmp.ridx(kk++) = lhs.ridx(i); + } + } + stmp.cidx(j+1) = kk; + } + + lhs = stmp; + } + } + else if (n == 0 && m == 0) + { + if (! ((rhs_nr == 1 && rhs_nc == 1) + || (rhs_nr == 0 || rhs_nc == 0))) + { + (*current_liboctave_error_handler) + ("A([], []) = X: X must be an empty matrix or a scalar"); + + retval = 0; + } + } + else + { + (*current_liboctave_error_handler) + ("A(I, J) = X: X must be a scalar or the number of elements in I must"); + (*current_liboctave_error_handler) + ("match the number of rows in X and the number of elements in J must"); + (*current_liboctave_error_handler) + ("match the number of columns in X"); + + retval = 0; + } + } + } + // idx_vector::freeze() printed an error message for us. + } + else if (n_idx == 1) + { + int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0; + + if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1)) + { + int lhs_len = lhs.length (); + + int n = idx_i.freeze (lhs_len, 0, true, liboctave_wrore_flag); + idx_i.sort (true); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + { + if (n != 0 && (lhs_nr != 0 || lhs_nc != 0)) + lhs.maybe_delete_elements (idx_i); + } + else + { + if (liboctave_wfi_flag) + { + if (lhs_is_empty + && idx_i.is_colon () + && ! (rhs_nr == 1 || rhs_nc == 1)) + { + (*current_liboctave_warning_handler) + ("A(:) = X: X is not a vector or scalar"); + } + else + { + int idx_nr = idx_i.orig_rows (); + int idx_nc = idx_i.orig_columns (); + + if (! (rhs_nr == idx_nr && rhs_nc == idx_nc)) + (*current_liboctave_warning_handler) + ("A(I) = X: X does not have same shape as I"); + } + } + + if (! assign1 ((Sparse&) lhs, (Sparse&) rhs)) + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + else if (lhs_nr == 1) + { + idx_i.freeze (lhs_nc, "vector", true, liboctave_wrore_flag); + idx_i.sort (true); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + lhs.maybe_delete_elements (idx_i); + else if (! assign1 ((Sparse&) lhs, (Sparse&) rhs)) + retval = 0; + } + // idx_vector::freeze() printed an error message for us. + } + else if (lhs_nc == 1) + { + idx_i.freeze (lhs_nr, "vector", true, liboctave_wrore_flag); + idx_i.sort (true); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + lhs.maybe_delete_elements (idx_i); + else if (! assign1 ((Sparse&) lhs, (Sparse&) rhs)) + retval = 0; + } + // idx_vector::freeze() printed an error message for us. + } + else + { + if (liboctave_wfi_flag + && ! (idx_i.is_colon () + || (idx_i.one_zero_only () + && idx_i.orig_rows () == lhs_nr + && idx_i.orig_columns () == lhs_nc))) + (*current_liboctave_warning_handler) + ("single index used for matrix"); + + int lhs_len = lhs.length (); + + int len = idx_i.freeze (lhs_nr * lhs_nc, "matrix"); + idx_i.sort (true); + + if (idx_i) + { + // Take a constant copy of lhs. This means that elem won't + // create missing elements. + const Sparse c_lhs (lhs); + + if (rhs_nr == 0 && rhs_nc == 0) + lhs.maybe_delete_elements (idx_i); + else if (len == 0) + { + if (! ((rhs_nr == 1 && rhs_nc == 1) + || (rhs_nr == 0 || rhs_nc == 0))) + (*current_liboctave_error_handler) + ("A([]) = X: X must be an empty matrix or scalar"); + } + else if (len == rhs_nr * rhs_nc) + { + int new_nnz = lhs_nz; + + // First count the number of non-zero elements + for (int i = 0; i < len; i++) + { + OCTAVE_QUIT; + + int ii = idx_i.elem (i); + if (ii < lhs_len && c_lhs.elem(ii) != LT ()) + new_nnz--; + if (rhs.elem(i) != RT ()) + new_nnz++; + } + + Sparse stmp (lhs_nr, lhs_nc, new_nnz); + + int i = 0; + int ii = 0; + int ic = 0; + if (i < lhs_nz) + { + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + ii = ic * lhs_nr + c_lhs.ridx(i); + } + + int j = 0; + int jj = idx_i.elem (j); + int jr = jj % lhs_nr; + int jc = (jj - jr) / lhs_nr; + + int kk = 0; + int kc = 0; + + while (j < len || i < lhs_nz) + { + if (j == len || (i < lhs_nz && ii < jj)) + { + while (kc <= ic) + stmp.xcidx (kc++) = kk; + stmp.xdata (kk) = c_lhs.data (i); + stmp.xridx (kk++) = c_lhs.ridx (i); + i++; + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + if (i < lhs_nz) + ii = ic * lhs_nr + c_lhs.ridx(i); + } + else + { + while (kc <= jc) + stmp.xcidx (kc++) = kk; + RT rtmp = rhs.elem (j); + if (rtmp != RT ()) + { + stmp.xdata (kk) = rtmp; + stmp.xridx (kk++) = jr; + } + if (ii == jj) + { + i++; + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + if (i < lhs_nz) + ii = ic * lhs_nr + c_lhs.ridx(i); + } + j++; + if (j < len) + { + jj = idx_i.elem (j); + jr = jj % lhs_nr; + jc = (jj - jr) / lhs_nr; + } + } + } + + for (int iidx = kc; iidx < lhs_nc+1; iidx++) + stmp.xcidx(iidx) = kk; + + + lhs = stmp; + } + else if (rhs_nr == 1 && rhs_nc == 1) + { + RT scalar = rhs.elem (0, 0); + int new_nnz = lhs_nz; + + // First count the number of non-zero elements + if (scalar != RT ()) + new_nnz += len; + for (int i = 0; i < len; i++) + { + OCTAVE_QUIT; + int ii = idx_i.elem (i); + if (ii < lhs_len && c_lhs.elem(ii) != LT ()) + new_nnz--; + } + + Sparse stmp (lhs_nr, lhs_nc, new_nnz); + + int i = 0; + int ii = 0; + int ic = 0; + if (i < lhs_nz) + { + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + ii = ic * lhs_nr + c_lhs.ridx(i); + } + + int j = 0; + int jj = idx_i.elem (j); + int jr = jj % lhs_nr; + int jc = (jj - jr) / lhs_nr; + + int kk = 0; + int kc = 0; + + while (j < len || i < lhs_nz) + { + if (j == len || (i < lhs_nz && ii < jj)) + { + while (kc <= ic) + stmp.xcidx (kc++) = kk; + stmp.xdata (kk) = c_lhs.data (i); + stmp.xridx (kk++) = c_lhs.ridx (i); + i++; + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + if (i < lhs_nz) + ii = ic * lhs_nr + c_lhs.ridx(i); + } + else + { + while (kc <= jc) + stmp.xcidx (kc++) = kk; + if (scalar != RT ()) + { + stmp.xdata (kk) = scalar; + stmp.xridx (kk++) = jr; + } + if (ii == jj) + { + i++; + while (ic < lhs_nc && i >= c_lhs.cidx(ic+1)) + ic++; + if (i < lhs_nz) + ii = ic * lhs_nr + c_lhs.ridx(i); + } + j++; + if (j < len) + { + jj = idx_i.elem (j); + jr = jj % lhs_nr; + jc = (jj - jr) / lhs_nr; + } + } + } + + for (int iidx = kc; iidx < lhs_nc+1; iidx++) + stmp.xcidx(iidx) = kk; + + lhs = stmp; + } + else + { + (*current_liboctave_error_handler) + ("A(I) = X: X must be a scalar or a matrix with the same size as I"); + + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + } + else + { + (*current_liboctave_error_handler) + ("invalid number of indices for matrix expression"); + + retval = 0; + } + + lhs.clear_index (); + + return retval; +} + +template +void +Sparse::print_info (std::ostream& os, const std::string& prefix) const +{ + os << prefix << "rep address: " << rep << "\n" + << prefix << "rep->nnz: " << rep->nnz << "\n" + << prefix << "rep->nrows: " << rep->nrows << "\n" + << prefix << "rep->ncols: " << rep->ncols << "\n" + << prefix << "rep->data: " << static_cast (rep->d) << "\n" + << prefix << "rep->ridx: " << static_cast (rep->r) << "\n" + << prefix << "rep->cidx: " << static_cast (rep->c) << "\n" + << prefix << "rep->count: " << rep->count << "\n"; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/Sparse.h b/liboctave/Sparse.h new file mode 100644 --- /dev/null +++ b/liboctave/Sparse.h @@ -0,0 +1,536 @@ +// Template sparse classes +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_Sparse_h) +#define octave_Sparse_h 1 + +#include +#include + +#include + +#include "Array.h" +#include "Array2.h" +#include "dim-vector.h" +#include "lo-utils.h" + +class idx_vector; + +// Two dimensional sparse class. Handles the reference counting for +// all the derived classes. + +template +class +Sparse +{ +protected: + //-------------------------------------------------------------------- + // The real representation of all Sparse arrays. + //-------------------------------------------------------------------- + + class SparseRep + { + public: + + T *d; + int *r; + int *c; + int nnz; + int nrows; + int ncols; + int count; + + SparseRep (void) : d (0), r (0), c (new int [1]), nnz (0), nrows (0), + ncols (0), count (1) { c[0] = 0; } + + SparseRep (int n) : d (0), r (0), c (new int [n+1]), nnz (0), nrows (n), + ncols (n), count (1) + { + for (int i = 0; i < n + 1; i++) + c[i] = 0; + } + + SparseRep (int nr, int nc) : d (0), r (0), c (new int [nc+1]), nnz (0), + nrows (nr), ncols (nc), count (1) + { + for (int i = 0; i < nc + 1; i++) + c[i] = 0; + } + + SparseRep (int nr, int nc, int nz) : d (new T [nz]), + r (new int [nz]), c (new int [nc+1]), nnz (nz), nrows (nr), + ncols (nc), count (1) + { + for (int i = 0; i < nc + 1; i++) + c[i] = 0; + } + + SparseRep (const SparseRep& a) + : d (new T [a.nnz]), r (new int [a.nnz]), c (new int [a.ncols + 1]), + nnz (a.nnz), nrows (a.nrows), ncols (a.ncols), count (1) + { + for (int i = 0; i < nnz; i++) + { + d[i] = a.d[i]; + r[i] = a.r[i]; + } + for (int i = 0; i < ncols + 1; i++) + c[i] = a.c[i]; + } + + ~SparseRep (void) { delete [] d; delete [] r; delete [] c; } + + int length (void) const { return nnz; } + + int nonzero (void) const { return c [ncols]; } + + T& elem (int _r, int _c); + + T celem (int _r, int _c) const; + + T& data (int i) { return d[i]; } + + T cdata (int i) const { return d[i]; } + + int& ridx (int i) { return r[i]; } + + int cridx (int i) const { return r[i]; } + + int& cidx (int i) { return c[i]; } + + int ccidx (int i) const { return c[i]; } + + void maybe_compress (bool remove_zeros); + + void change_length (int nz); + + private: + + // No assignment! + + SparseRep& operator = (const SparseRep& a); + }; + + //-------------------------------------------------------------------- + + void make_unique (void) + { + if (rep->count > 1) + { + --rep->count; + rep = new SparseRep (*rep); + } + } + +public: + + // !!! WARNING !!! -- these should be protected, not public. You + // should not access these data members directly! + + typename Sparse::SparseRep *rep; + + dim_vector dimensions; + +protected: + idx_vector *idx; + int idx_count; + +private: + + typename Sparse::SparseRep *nil_rep (void) const + { + static typename Sparse::SparseRep *nr + = new typename Sparse::SparseRep (); + + nr->count++; + + return nr; + } + +public: + + Sparse (void) + : rep (nil_rep ()), dimensions (dim_vector(0,0)), + idx (0), idx_count (0) { } + + explicit Sparse (int n) + : rep (new typename Sparse::SparseRep (n)), + dimensions (dim_vector (n, n)), idx (0), idx_count (0) { } + + explicit Sparse (int nr, int nc) + : rep (new typename Sparse::SparseRep (nr, nc)), + dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { } + + explicit Sparse (int nr, int nc, T val); + + Sparse (const dim_vector& dv, int nz) + : rep (new typename Sparse::SparseRep (dv(0), dv(1), nz)), + dimensions (dv), idx (0), idx_count (0) { } + + Sparse (int nr, int nc, int nz) + : rep (new typename Sparse::SparseRep (nr, nc, nz)), + dimensions (dim_vector (nr, nc)), idx (0), idx_count (0) { } + + // Type conversion case. + template Sparse (const Sparse& a); + + // No type conversion case. + Sparse (const Sparse& a) + : rep (a.rep), dimensions (a.dimensions), idx (0), idx_count (0) + { + rep->count++; + } + +public: + + Sparse (const dim_vector& dv); + + Sparse (const Sparse& a, const dim_vector& dv); + + Sparse (const Array& a, const Array& r, const Array& c, + int nr, int nc, bool sum_terms); + + Sparse (const Array& a, const Array& r, const Array& c, + int nr, int nc, bool sum_terms); + + // Sparsify a normal matrix + Sparse (const Array2& a); + Sparse (const Array& a); + + virtual ~Sparse (void); + + Sparse& operator = (const Sparse& a) + { + if (this != &a) + { + if (--rep->count <= 0) + delete rep; + + rep = a.rep; + rep->count++; + + dimensions = a.dimensions; + } + + idx_count = 0; + idx = 0; + + return *this; + } + + // Note that capacity and nnz are the amount of storage for non-zero + // elements, while nonzero is the actual number of non-zero terms + int capacity (void) const { return rep->length (); } + int nnz (void) const { return capacity (); } + int nonzero (void) const { return rep->nonzero (); } + + // Paranoid number of elements test for case of dims = (-1,-1) + int numel (void) const + { + if (dim1() < 0 || dim2() < 0) + return 0; + else + return dimensions.numel (); + } + + int nelem (void) const { return capacity (); } + int length (void) const { return numel (); } + + int dim1 (void) const { return dimensions(0); } + int dim2 (void) const { return dimensions(1); } + + int rows (void) const { return dim1 (); } + int cols (void) const { return dim2 (); } + int columns (void) const { return dim2 (); } + + int get_row_index (int k) { return ridx (k); } + int get_col_index (int k) + { + int ret = 0; + while (cidx(ret+1) < k) + ret++; + return ret; + } + size_t byte_size (void) const { return (cols () + 1) * sizeof (int) + + capacity () * (sizeof (T) + sizeof (int)); } + + dim_vector dims (void) const { return dimensions; } + + Sparse squeeze (void) const { return *this; } + + int compute_index (const Array& ra_idx) const; + + T range_error (const char *fcn, int n) const; + T& range_error (const char *fcn, int n); + + T range_error (const char *fcn, int i, int j) const; + T& range_error (const char *fcn, int i, int j); + + T range_error (const char *fcn, const Array& ra_idx) const; + T& range_error (const char *fcn, const Array& ra_idx); + + // No checking, even for multiple references, ever. + + T& xelem (int n) + { + int i = n % rows (), j = n / rows(); + return xelem (i, j); + } + + T xelem (int n) const + { + int i = n % rows (), j = n / rows(); + return xelem (i, j); + } + + T& xelem (int i, int j) { return rep->elem (i, j); } + T xelem (int i, int j) const { return rep->celem (i, j); } + + T& xelem (const Array& ra_idx) + { return xelem (compute_index (ra_idx)); } + + T xelem (const Array& ra_idx) const + { return xelem (compute_index (ra_idx)); } + + // XXX FIXME XXX -- would be nice to fix this so that we don't + // unnecessarily force a copy, but that is not so easy, and I see no + // clean way to do it. + + T& checkelem (int n) + { + if (n < 0 || n >= numel ()) + return range_error ("T& Sparse::checkelem", n); + else + { + make_unique (); + return xelem (n); + } + } + + T& checkelem (int i, int j) + { + if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) + return range_error ("T& Sparse::checkelem", i, j); + else + { + make_unique (); + return xelem (i, j); + } + } + + T& checkelem (const Array& ra_idx) + { + int i = compute_index (ra_idx); + + if (i < 0) + return range_error ("T& Sparse::checkelem", ra_idx); + else + return elem (i); + } + + T& elem (int n) + { + make_unique (); + return xelem (n); + } + + T& elem (int i, int j) + { + make_unique (); + return xelem (i, j); + } + + T& elem (const Array& ra_idx) + { return Sparse::elem (compute_index (ra_idx)); } + +#if defined (BOUNDS_CHECKING) + T& operator () (int n) { return checkelem (n); } + T& operator () (int i, int j) { return checkelem (i, j); } + T& operator () (const Array& ra_idx) { return checkelem (ra_idx); } +#else + T& operator () (int n) { return elem (n); } + T& operator () (int i, int j) { return elem (i, j); } + T& operator () (const Array& ra_idx) { return elem (ra_idx); } +#endif + + T checkelem (int n) const + { + if (n < 0 || n >= numel ()) + return range_error ("T Sparse::checkelem", n); + else + return xelem (n); + } + + T checkelem (int i, int j) const + { + if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) + return range_error ("T Sparse::checkelem", i, j); + else + return xelem (i, j); + } + + T checkelem (const Array& ra_idx) const + { + int i = compute_index (ra_idx); + + if (i < 0) + return range_error ("T Sparse::checkelem", ra_idx); + else + return Sparse::elem (i); + } + + T elem (int n) const { return xelem (n); } + + T elem (int i, int j) const { return xelem (i, j); } + + T elem (const Array& ra_idx) const + { return Sparse::elem (compute_index (ra_idx)); } + +#if defined (BOUNDS_CHECKING) + T operator () (int n) const { return checkelem (n); } + T operator () (int i, int j) const { return checkelem (i, j); } + T operator () (const Array& ra_idx) const { return checkelem (ra_idx); } +#else + T operator () (int n) const { return elem (n); } + T operator () (int i, int j) const { return elem (i, j); } + T operator () (const Array& ra_idx) const { return elem (ra_idx); } +#endif + + Sparse maybe_compress (bool remove_zeros = false) + { rep->maybe_compress (remove_zeros); return (*this); } + + Sparse reshape (const dim_vector& new_dims) const; + + // !!! WARNING !!! -- the following resize_no_fill functions are + // public because template friends don't work properly with versions + // of gcc earlier than 3.3. You should use these functions only in + // classes that are derived from Sparse. + + // protected: + + void resize_no_fill (int r, int c); + + void resize_no_fill (const dim_vector& dv); + +public: + Sparse permute (const Array& vec, bool inv = false) const; + + Sparse ipermute (const Array& vec) const + { return permute (vec, true); } + + void resize (int r, int c) { resize_no_fill (r, c); } + + void resize (const dim_vector& dv) { resize_no_fill (dv); } + + void change_capacity (int nz) { rep->change_length (nz); } + + Sparse& insert (const Sparse& a, int r, int c); + Sparse& insert (const Sparse& a, const Array& idx); + + bool is_square (void) const { return (dim1 () == dim2 ()); } + + bool is_empty (void) const { return (rows () < 1 && cols () < 1); } + + Sparse transpose (void) const; + + T* data (void) { make_unique (); return rep->d; } + T& data (int i) { make_unique (); return rep->data (i); } + T* xdata (void) { return rep->d; } + T& xdata (int i) { return rep->data (i); } + + T data (int i) const { return rep->data (i); } + T* data (void) const { return rep->d; } + + int* ridx (void) { make_unique (); return rep->r; } + int& ridx (int i) { make_unique (); return rep->ridx (i); } + int* xridx (void) { return rep->r; } + int& xridx (int i) { return rep->ridx (i); } + + int ridx (int i) const { return rep->cridx (i); } + int* ridx (void) const { return rep->r; } + + int* cidx (void) { make_unique (); return rep->c; } + int& cidx (int i) { make_unique (); return rep->cidx (i); } + int* xcidx (void) { return rep->c; } + int& xcidx (int i) { return rep->cidx (i); } + + int cidx (int i) const { return rep->ccidx (i); } + int* cidx (void) const { return rep->c; } + + int ndims (void) const { return dimensions.length (); } + + void clear_index (void); + + void set_index (const idx_vector& i); + + int index_count (void) const { return idx_count; } + + idx_vector *get_idx (void) const { return idx; } + + void maybe_delete_elements (idx_vector& i); + + void maybe_delete_elements (idx_vector& i, idx_vector& j); + + void maybe_delete_elements (Array& ra_idx); + + Sparse value (void); + + Sparse index (idx_vector& i, int resize_ok = 0) const; + + Sparse index (idx_vector& i, idx_vector& j, int resize_ok = 0) const; + + Sparse index (Array& ra_idx, int resize_ok = 0) const; + + void print_info (std::ostream& os, const std::string& prefix) const; + +}; + +// NOTE: these functions should be friends of the Sparse class and +// Sparse::dimensions should be protected, not public, but we can't +// do that because of bugs in gcc prior to 3.3. + +template +/* friend */ int +assign (Sparse& lhs, const Sparse& rhs); + +template +/* friend */ int +assign1 (Sparse& lhs, const Sparse& rhs); + +#define INSTANTIATE_SPARSE_ASSIGN(LT, RT) \ + template int assign (Sparse&, const Sparse&); \ + template int assign1 (Sparse&, const Sparse&); + +#define INSTANTIATE_SPARSE(T) \ + template class Sparse; + +#define INSTANTIATE_SPARSE_AND_ASSIGN(T) \ + INSTANTIATE_SPARSE (T); \ + INSTANTIATE_SPARSE_ASSIGN (T, T) + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/SparseCmplxLU.cc b/liboctave/SparseCmplxLU.cc new file mode 100644 --- /dev/null +++ b/liboctave/SparseCmplxLU.cc @@ -0,0 +1,405 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "lo-error.h" + +#include "SparseCmplxLU.h" +#include "oct-spparms.h" + +// Instantiate the base LU class for the types we need. + +#include "sparse-base-lu.h" +#include "sparse-base-lu.cc" + +template class sparse_base_lu ; + +// Include the UMFPACK functions +extern "C" { +#include "umfpack.h" +} + +SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, + double piv_thres) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_zi_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_zi_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const Complex *Ax = a.data (); + + umfpack_zi_report_matrix (nr, nc, Ap, Ai, X_CAST (const double *, Ax), + NULL, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_zi_qsymbolic (nr, nc, Ap, Ai, + X_CAST (const double *, Ax), NULL, NULL, + &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU symbolic factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + umfpack_zi_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_zi_numeric (Ap, Ai, X_CAST (const double *, Ax), NULL, + Symbolic, &Numeric, control, info) ; + umfpack_zi_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU numeric factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + { + umfpack_zi_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_zi_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseComplexMatrix (n_inner, nr, 1); + else + Lfact = SparseComplexMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + Complex *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseComplexMatrix (n_inner, nc, 1); + else + Ufact = SparseComplexMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + Complex *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_zi_get_numeric (Ltp, Ltj, X_CAST (double *, Ltx), + NULL, Up, Uj, + X_CAST (double *, Ux), NULL, p, + q, NULL, NULL, &do_recip, + NULL, Numeric) ; + + umfpack_zi_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); + + umfpack_zi_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + + umfpack_zi_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), + X_CAST (double *, Lfact.data()), + NULL, 1, control); + + umfpack_zi_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), + X_CAST (double *, Ufact.data()), + NULL, 1, control); + umfpack_zi_report_perm (nr, p, control); + umfpack_zi_report_perm (nc, q, control); + } + + umfpack_zi_report_info (control, info); + } + } + } +} + +SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, + const ColumnVector& Qinit, + double piv_thres, bool FixedQ) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_zi_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + if (FixedQ) + Control (UMFPACK_FIXQ) = 1.0; + else + { + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + } + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_zi_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const Complex *Ax = a.data (); + + umfpack_zi_report_matrix (nr, nc, Ap, Ai, X_CAST (const double *, Ax), NULL, + 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status; + + // Null loop so that qinit is imediately deallocated when not needed + do { + OCTAVE_LOCAL_BUFFER (int, qinit, nc); + + for (int i = 0; i < nc; i++) + qinit [i] = static_cast (Qinit (i)); + + status = umfpack_zi_qsymbolic (nr, nc, Ap, Ai, X_CAST (const double *, Ax), + NULL, qinit, &Symbolic, control, info); + } while (0); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU symbolic factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + umfpack_zi_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_zi_numeric (Ap, Ai, X_CAST (const double *, Ax), NULL, + Symbolic, &Numeric, control, info) ; + umfpack_zi_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU numeric factorization failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + { + umfpack_zi_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_zi_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); + + umfpack_zi_report_status (control, status); + umfpack_zi_report_info (control, info); + + umfpack_zi_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseComplexMatrix (n_inner, nr, 1); + else + Lfact = SparseComplexMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + Complex *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseComplexMatrix (n_inner, nc, 1); + else + Ufact = SparseComplexMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + Complex *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_zi_get_numeric (Ltp, Ltj, X_CAST (double *, Ltx), + NULL, Up, Uj, + X_CAST (double *, Ux), NULL, p, + q, NULL, NULL, &do_recip, + NULL, Numeric) ; + + umfpack_zi_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); + + umfpack_zi_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + + umfpack_zi_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), + X_CAST (double *, Lfact.data()), + NULL, 1, control); + + umfpack_zi_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), + X_CAST (double *, Ufact.data()), + NULL, 1, control); + umfpack_zi_report_perm (nr, p, control); + umfpack_zi_report_perm (nc, q, control); + } + + umfpack_zi_report_info (control, info); + } + } + } +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ + diff --git a/liboctave/SparseCmplxLU.h b/liboctave/SparseCmplxLU.h new file mode 100644 --- /dev/null +++ b/liboctave/SparseCmplxLU.h @@ -0,0 +1,64 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_complex_LU_h) +#define octave_sparse_complex_LU_h 1 + +#include "sparse-base-lu.h" +#include "dSparse.h" +#include "CSparse.h" + +class +SparseComplexLU + : public sparse_base_lu +{ +public: + + SparseComplexLU (void) + : sparse_base_lu () { } + + SparseComplexLU (const SparseComplexMatrix& a, double piv_thres = -1); + + SparseComplexLU (const SparseComplexMatrix& a, const ColumnVector& Qinit, + double piv_thres = -1, bool FixedQ = false); + + SparseComplexLU (const SparseComplexLU& a) + : sparse_base_lu (a) { } + + SparseComplexLU& operator = (const SparseComplexLU& a) + { + if (this != &a) + sparse_base_lu + :: operator = (a); + + return *this; + } + + ~SparseComplexLU (void) { } +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/SparseType.cc b/liboctave/SparseType.cc new file mode 100644 --- /dev/null +++ b/liboctave/SparseType.cc @@ -0,0 +1,696 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "SparseType.h" +#include "dSparse.h" +#include "CSparse.h" +#include "oct-spparms.h" + +// XXX FIXME XXX There is a large code duplication here + +SparseType::SparseType (const SparseType &a) : typ (a.typ), + sp_bandden (a.sp_bandden), bandden (a.bandden), + upper_band (a.upper_band), lower_band (a.lower_band), + dense (a.dense), nperm (a.nperm) +{ + if (nperm != 0) + { + row_perm = new int [nperm]; + col_perm = new int [nperm]; + for (int i = 0; i < nperm; i++) + { + row_perm[i] = a.row_perm[i]; + col_perm[i] = a.col_perm[i]; + } + } +} + +SparseType::SparseType (const SparseMatrix &a) +{ + int nrows = a.rows (); + int ncols = a.cols (); + int nnz = a.nnz (); + + nperm = 0; + + if (nrows != ncols) + typ = SparseType::Rectangular; + else + { + sp_bandden = Voctave_sparse_controls.get_key ("bandden"); + bool maybe_hermitian = false; + typ = SparseType::Full; + + if (nnz == ncols) + { + matrix_type tmp_typ = SparseType::Diagonal; + int i; + // Maybe the matrix is diagonal + for (i = 0; i < ncols; i++) + { + if (a.cidx(i+1) != a.cidx(i) + 1) + { + tmp_typ = Full; + break; + } + if (a.ridx(i) != i) + { + tmp_typ = SparseType::Permuted_Diagonal; + break; + } + } + + if (tmp_typ == SparseType::Permuted_Diagonal) + { + bool found [ncols]; + + for (int j = 0; j < i; j++) + found [j] = true; + for (int j = i; j < ncols; j++) + found [j] = false; + + for (int j = i; j < ncols; j++) + { + if ((a.cidx(j+1) != a.cidx(j) + 1) || found [a.ridx(j)]) + { + tmp_typ = Full; + break; + } + found [a.ridx(j)] = true; + } + } + typ = tmp_typ; + } + + if (typ == Full) + { + // Search for banded, upper and lower triangular matrices + bool singular = false; + upper_band = 0; + lower_band = 0; + for (int j = 0; j < ncols; j++) + { + bool zero_on_diagonal = true; + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + if (a.ridx(i) == j) + { + zero_on_diagonal = false; + break; + } + + if (zero_on_diagonal) + { + singular = true; + break; + } + + if (a.cidx(j+1) - a.cidx(j) > 0) + { + int ru = a.ridx(a.cidx(j)); + int rl = a.ridx(a.cidx(j+1)-1); + + if (j - ru > upper_band) + upper_band = j - ru; + + if (rl - j > lower_band) + lower_band = rl - j; + } + } + + if (!singular) + { + bandden = double (nnz) / + (double (ncols) * (double (lower_band) + + double (upper_band)) - + 0.5 * double (upper_band + 1) * double (upper_band) - + 0.5 * double (lower_band + 1) * double (lower_band)); + + if (sp_bandden != 1. && bandden > sp_bandden) + { + if (upper_band == 1 && lower_band == 1) + typ = SparseType::Tridiagonal; + else + typ = SparseType::Banded; + + int nnz_in_band = (upper_band + lower_band + 1) * nrows - + (1 + upper_band) * upper_band / 2 - + (1 + lower_band) * lower_band / 2; + if (nnz_in_band == nnz) + dense = true; + else + dense = false; + } + else if (upper_band == 0) + typ = SparseType::Lower; + else if (lower_band == 0) + typ = SparseType::Upper; + + if (upper_band == lower_band) + maybe_hermitian = true; + } + + if (typ == Full) + { + // Search for a permuted triangular matrix, and test if + // permutation is singular + + // XXX FIXME XXX Write this test based on dmperm + + } + } + + if (maybe_hermitian && (typ == Full || typ == Tridiagonal || + typ == Banded)) + { + // Check for symmetry, with positive real diagonal, which + // has a very good chance of being symmetric positive + // definite.. + bool is_herm = true; + + for (int j = 0; j < ncols; j++) + { + bool diag_positive = false; + + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + int ri = a.ridx(i); + + if (ri == j) + { + if (a.data(i) == std::abs(a.data(i))) + diag_positive = true; + else + break; + } + else + { + bool found = false; + + for (int k = a.cidx(ri); k < a.cidx(ri+1); k++) + { + if (a.ridx(k) == j) + { + if (a.data(i) == conj (a.data(k))) + found = true; + break; + } + } + + if (! found) + { + is_herm = false; + break; + } + } + } + + if (! diag_positive || ! is_herm) + { + is_herm = false; + break; + } + } + + if (is_herm) + { + if (typ == Full) + typ = Hermitian; + else if (typ == Banded) + typ = Banded_Hermitian; + else + typ = Tridiagonal_Hermitian; + } + } + } +} + +SparseType::SparseType (const SparseComplexMatrix &a) +{ + int nrows = a.rows (); + int ncols = a.cols (); + int nnz = a.nnz (); + + nperm = 0; + + if (nrows != ncols) + typ = SparseType::Rectangular; + else + { + sp_bandden = Voctave_sparse_controls.get_key ("bandden"); + bool maybe_hermitian = false; + typ = SparseType::Full; + + if (nnz == ncols) + { + matrix_type tmp_typ = SparseType::Diagonal; + int i; + // Maybe the matrix is diagonal + for (i = 0; i < ncols; i++) + { + if (a.cidx(i+1) != a.cidx(i) + 1) + { + tmp_typ = Full; + break; + } + if (a.ridx(i) != i) + { + tmp_typ = SparseType::Permuted_Diagonal; + break; + } + } + + if (tmp_typ == SparseType::Permuted_Diagonal) + { + bool found [ncols]; + + for (int j = 0; j < i; j++) + found [j] = true; + for (int j = i; j < ncols; j++) + found [j] = false; + + for (int j = i; j < ncols; j++) + { + if ((a.cidx(j+1) != a.cidx(j) + 1) || found [a.ridx(j)]) + { + tmp_typ = Full; + break; + } + found [a.ridx(j)] = true; + } + } + typ = tmp_typ; + } + + if (typ == Full) + { + // Search for banded, upper and lower triangular matrices + bool singular = false; + upper_band = 0; + lower_band = 0; + for (int j = 0; j < ncols; j++) + { + bool zero_on_diagonal = true; + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + if (a.ridx(i) == j) + { + zero_on_diagonal = false; + break; + } + + if (zero_on_diagonal) + { + singular = true; + break; + } + + if (a.cidx(j+1) - a.cidx(j) > 0) + { + int ru = a.ridx(a.cidx(j)); + int rl = a.ridx(a.cidx(j+1)-1); + + if (j - ru > upper_band) + upper_band = j - ru; + + if (rl - j > lower_band) + lower_band = rl - j; + } + } + + if (!singular) + { + bandden = double (nnz) / + (double (ncols) * (double (lower_band) + + double (upper_band)) - + 0.5 * double (upper_band + 1) * double (upper_band) - + 0.5 * double (lower_band + 1) * double (lower_band)); + + if (sp_bandden != 1. && bandden > sp_bandden) + { + if (upper_band == 1 && lower_band == 1) + typ = SparseType::Tridiagonal; + else + typ = SparseType::Banded; + + int nnz_in_band = (upper_band + lower_band + 1) * nrows - + (1 + upper_band) * upper_band / 2 - + (1 + lower_band) * lower_band / 2; + if (nnz_in_band == nnz) + dense = true; + else + dense = false; + } + else if (upper_band == 0) + typ = SparseType::Lower; + else if (lower_band == 0) + typ = SparseType::Upper; + + if (upper_band == lower_band) + maybe_hermitian = true; + } + + if (typ == Full) + { + // Search for a permuted triangular matrix, and test if + // permutation is singular + + // XXX FIXME XXX Write this test based on dmperm + + } + } + + if (maybe_hermitian && (typ == Full || typ == Tridiagonal || + typ == Banded)) + { + // Check for symmetry, with positive real diagonal, which + // has a very good chance of being symmetric positive + // definite.. + bool is_herm = true; + + for (int j = 0; j < ncols; j++) + { + bool diag_positive = false; + + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + int ri = a.ridx(i); + + if (ri == j) + { + if (a.data(i) == std::abs(a.data(i))) + diag_positive = true; + else + break; + } + else + { + bool found = false; + + for (int k = a.cidx(ri); k < a.cidx(ri+1); k++) + { + if (a.ridx(k) == j) + { + if (a.data(i) == a.data(k)) + found = true; + break; + } + } + + if (! found) + { + is_herm = false; + break; + } + } + } + + if (! diag_positive || ! is_herm) + { + is_herm = false; + break; + } + } + + if (is_herm) + { + if (typ == Full) + typ = Hermitian; + else if (typ == Banded) + typ = Banded_Hermitian; + else + typ = Tridiagonal_Hermitian; + } + } + } +} + +SparseType::~SparseType (void) +{ + if (nperm != 0) + { + delete [] row_perm; + delete [] col_perm; + } +} + +SparseType& +SparseType::operator = (const SparseType& a) +{ + if (this != &a) + { + typ = a.typ; + sp_bandden = a.sp_bandden; + bandden = a.bandden; + upper_band = a.upper_band; + lower_band = a.lower_band; + dense = a.dense; + nperm = a.nperm; + + if (nperm != 0) + { + row_perm = new int [nperm]; + col_perm = new int [nperm]; + for (int i = 0; i < nperm; i++) + { + row_perm[i] = a.row_perm[i]; + col_perm[i] = a.col_perm[i]; + } + } + + } + return *this; +} + +int +SparseType::type (const SparseMatrix &a) +{ + if (typ != SparseType::Unknown && + sp_bandden == Voctave_sparse_controls.get_key ("bandden")) + { + if (Voctave_sparse_controls.get_key ("spumoni") != 0.) + (*current_liboctave_warning_handler) + ("Using Cached Sparse Matrix Type"); + + return typ; + } + + if (Voctave_sparse_controls.get_key ("spumoni") != 0.) + (*current_liboctave_warning_handler) + ("Calculating Sparse Matrix Type"); + + + SparseType tmp_typ (a); + typ = tmp_typ.typ; + sp_bandden = tmp_typ.sp_bandden; + bandden = tmp_typ.bandden; + upper_band = tmp_typ.upper_band; + lower_band = tmp_typ.lower_band; + dense = tmp_typ.dense; + nperm = tmp_typ.nperm; + + if (nperm != 0) + { + row_perm = new int [nperm]; + col_perm = new int [nperm]; + for (int i = 0; i < nperm; i++) + { + row_perm[i] = tmp_typ.row_perm[i]; + col_perm[i] = tmp_typ.col_perm[i]; + } + } + + return typ; +} + +int +SparseType::type (const SparseComplexMatrix &a) +{ + if (typ != SparseType::Unknown && + sp_bandden == Voctave_sparse_controls.get_key ("bandden")) + { + if (Voctave_sparse_controls.get_key ("spumoni") != 0.) + (*current_liboctave_warning_handler) + ("Using Cached Sparse Matrix Type"); + + return typ; + } + + if (Voctave_sparse_controls.get_key ("spumoni") != 0.) + (*current_liboctave_warning_handler) + ("Calculating Sparse Matrix Type"); + + + SparseType tmp_typ (a); + typ = tmp_typ.typ; + sp_bandden = tmp_typ.sp_bandden; + bandden = tmp_typ.bandden; + upper_band = tmp_typ.upper_band; + lower_band = tmp_typ.lower_band; + dense = tmp_typ.dense; + nperm = tmp_typ.nperm; + + if (nperm != 0) + { + row_perm = new int [nperm]; + col_perm = new int [nperm]; + for (int i = 0; i < nperm; i++) + { + row_perm[i] = tmp_typ.row_perm[i]; + col_perm[i] = tmp_typ.col_perm[i]; + } + } + + return typ; +} + +void +SparseType::info (void) const +{ + if (Voctave_sparse_controls.get_key ("spumoni") != 0.) + { + if (typ == SparseType::Unknown) + (*current_liboctave_warning_handler) + ("Unknown Sparse Matrix Type"); + else if (typ == SparseType::Diagonal) + (*current_liboctave_warning_handler) + ("Diagonal Sparse Matrix"); + else if (typ == SparseType::Permuted_Diagonal) + (*current_liboctave_warning_handler) + ("Permuted Diagonal Sparse Matrix"); + else if (typ == SparseType::Upper) + (*current_liboctave_warning_handler) + ("Upper Triangular Sparse Matrix"); + else if (typ == SparseType::Lower) + (*current_liboctave_warning_handler) + ("Lower Triangular Sparse Matrix"); + else if (typ == SparseType::Permuted_Upper) + (*current_liboctave_warning_handler) + ("Permuted Upper Triangular Sparse Matrix"); + else if (typ == SparseType::Permuted_Lower) + (*current_liboctave_warning_handler) + ("Permuted Lower Triangular Sparse Matrix"); + else if (typ == SparseType::Banded) + (*current_liboctave_warning_handler) + ("Banded Sparse Matrix %g-1-%g (Density %g)", lower_band, + upper_band, bandden); + else if (typ == SparseType::Banded_Hermitian) + (*current_liboctave_warning_handler) + ("Banded Hermitian/Symmetric Sparse Matrix %g-1-%g (Density %g)", + lower_band, upper_band, bandden); + else if (typ == SparseType::Hermitian) + (*current_liboctave_warning_handler) + ("Hermitian/Symmetric Sparse Matrix"); + else if (typ == SparseType::Tridiagonal) + (*current_liboctave_warning_handler) + ("Tridiagonal Sparse Matrix"); + else if (typ == SparseType::Tridiagonal_Hermitian) + (*current_liboctave_warning_handler) + ("Hermitian/Symmetric Tridiagonal Sparse Matrix"); + else if (typ == SparseType::Rectangular) + (*current_liboctave_warning_handler) + ("Rectangular Sparse Matrix"); + else if (typ == SparseType::Full) + (*current_liboctave_warning_handler) + ("Full Sparse Matrix"); + } +} + +void +SparseType::mark_as_symmetric (void) +{ + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + typ = SparseType::Tridiagonal_Hermitian; + else if (typ == SparseType::Banded || + typ == SparseType::Banded_Hermitian) + typ = SparseType::Banded_Hermitian; + else if (typ == SparseType::Full || typ == SparseType::Hermitian || + typ == SparseType::Unknown) + typ = SparseType::Hermitian; + else + (*current_liboctave_error_handler) + ("Can not mark current matrix type as symmetric"); +} + +void +SparseType::mark_as_unsymmetric (void) +{ + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + typ = SparseType::Tridiagonal; + else if (typ == SparseType::Banded || + typ == SparseType::Banded_Hermitian) + typ = SparseType::Banded; + else if (typ == SparseType::Full || typ == SparseType::Hermitian || + typ == SparseType::Unknown) + typ = SparseType::Full; +} + +void +SparseType::mark_as_permuted (const int np, const int *pr, const int *pc) +{ + nperm = np; + row_perm = new int [nperm]; + col_perm = new int [nperm]; + for (int i = 0; i < nperm; i++) + { + row_perm[i] = pr[i]; + col_perm[i] = pc[i]; + } + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + typ = SparseType::Permuted_Diagonal; + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + typ = SparseType::Permuted_Upper; + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + typ = SparseType::Permuted_Lower; + else + (*current_liboctave_error_handler) + ("Can not mark current matrix type as symmetric"); +} + +void +SparseType::mark_as_unpermuted (void) +{ + if (nperm) + { + nperm = 0; + delete [] row_perm; + delete [] col_perm; + } + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + typ = SparseType::Diagonal; + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + typ = SparseType::Upper; + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + typ = SparseType::Lower; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ + diff --git a/liboctave/SparseType.h b/liboctave/SparseType.h new file mode 100644 --- /dev/null +++ b/liboctave/SparseType.h @@ -0,0 +1,155 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_SparseType_h) +#define octave_SparseType_h + +class SparseMatrix; +class SparseComplexMatrix; + +class +SparseType +{ +public: + enum matrix_type { + Unknown = 0, + Full, + Diagonal, + Permuted_Diagonal, + Upper, + Lower, + Permuted_Upper, + Permuted_Lower, + Banded, + Hermitian, + Banded_Hermitian, + Tridiagonal, + Tridiagonal_Hermitian, + Rectangular + }; + + SparseType (void) : typ (Unknown), nperm (0) { } + + SparseType (const SparseType &a); + + SparseType (const SparseMatrix &a); + + SparseType (const SparseComplexMatrix &a); + + ~SparseType (void); + + SparseType& operator = (const SparseType& a); + + int type (void) const { return typ; } + + int type (const SparseMatrix &a); + + int type (const SparseComplexMatrix &a); + + double band_density (void) const { return bandden; } + + int nupper (void) const { return upper_band; } + + int nlower (void) const { return lower_band; } + + bool is_dense (void) const { return dense; } + + bool is_diagonal (void) const + { return (typ == Diagonal || typ == Permuted_Diagonal); } + + bool is_upper_triangular (void) const + { return (typ == Upper || typ == Permuted_Upper); } + + bool is_lower_triangular (void) const + { return (typ == Lower || typ == Permuted_Lower); } + + bool is_banded (void) + { return (typ == Banded || typ == Banded_Hermitian); } + + bool is_tridiagonal (void) const + { return (typ == Tridiagonal || typ == Tridiagonal_Hermitian); } + + bool is_hermitian (void) const + { return (typ == Banded_Hermitian || typ == Tridiagonal_Hermitian || + typ == Hermitian); } + + bool is_rectangular (void) const { return (typ == Rectangular); } + + bool is_known (void) const { return (typ != Unknown); } + + bool is_unknown (void) const { return (typ == Unknown); } + + void info (void) const; + + int * triangular_row_perm (void) const { return row_perm; } + + int * triangular_col_perm (void) const { return col_perm; } + + void invaldate_type (void) { typ = Unknown; } + + void mark_as_diagonal (void) { typ = Diagonal; } + + void mark_as_upper_triangular (void) { typ = Upper; } + + void mark_as_lower_triangular (void) { typ = Lower; } + + void mark_as_tridiagonal (void) {typ = Tridiagonal; } + + void mark_as_banded (const int ku, const int kl) + { typ = Banded; upper_band = ku; lower_band = kl; } + + void mark_as_full (void) { typ = Full; } + + void mark_as_rectangular (void) { typ = Rectangular; } + + void mark_as_dense (void) { dense = true; } + + void mark_as_not_dense (void) { dense = false; } + + void mark_as_symmetric (void); + + void mark_as_unsymmetric (void); + + void mark_as_permuted (const int np, const int *pr, const int *pc); + + void mark_as_unpermuted (void); + +private: + void type (int new_typ) { typ = static_cast(new_typ); } + + matrix_type typ; + double sp_bandden; + double bandden; + int upper_band; + int lower_band; + bool dense; + int nperm; + int *row_perm; + int *col_perm; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/SparsedbleLU.cc b/liboctave/SparsedbleLU.cc new file mode 100644 --- /dev/null +++ b/liboctave/SparsedbleLU.cc @@ -0,0 +1,392 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "lo-error.h" + +#include "SparsedbleLU.h" +#include "oct-spparms.h" + +// Instantiate the base LU class for the types we need. + +#include "sparse-base-lu.h" +#include "sparse-base-lu.cc" + +template class sparse_base_lu ; + +// Include the UMFPACK functions +extern "C" { +#include "umfpack.h" +} + +SparseLU::SparseLU (const SparseMatrix& a, double piv_thres) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_di_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const double *Ax = a.data (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, NULL, + &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU symbolic factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + umfpack_di_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseMatrix (n_inner, nr, 1); + else + Lfact = SparseMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + double *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseMatrix (n_inner, nc, 1); + else + Ufact = SparseMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + double *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Uj, + Ux, p, q, (double *) NULL, + &do_recip, (double *) NULL, + Numeric) ; + + umfpack_di_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + + umfpack_di_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), Lfact.data (), + 1, control); + umfpack_di_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), Ufact.data (), + 1, control); + umfpack_di_report_perm (nr, p, control); + umfpack_di_report_perm (nc, q, control); + } + + umfpack_di_report_info (control, info); + } + } + } +} + +SparseLU::SparseLU (const SparseMatrix& a, const ColumnVector& Qinit, + double piv_thres, bool FixedQ) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + if (FixedQ) + Control (UMFPACK_FIXQ) = 1.0; + else + { + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + } + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_di_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const double *Ax = a.data (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status; + + // Null loop so that qinit is imediately deallocated when not needed + do { + OCTAVE_LOCAL_BUFFER (int, qinit, nc); + + for (int i = 0; i < nc; i++) + qinit [i] = static_cast (Qinit (i)); + + status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, qinit, + &Symbolic, control, info); + } while (0); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU symbolic factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + umfpack_di_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseMatrix (n_inner, nr, 1); + else + Lfact = SparseMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + double *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseMatrix (n_inner, nc, 1); + else + Ufact = SparseMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + double *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Uj, + Ux, p, q, (double *) NULL, + &do_recip, (double *) NULL, + Numeric) ; + + umfpack_di_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + umfpack_di_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), Lfact.data (), + 1, control); + umfpack_di_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), Ufact.data (), + 1, control); + umfpack_di_report_perm (nr, p, control); + umfpack_di_report_perm (nc, q, control); + } + + umfpack_di_report_info (control, info); + } + } + } +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ + diff --git a/liboctave/SparsedbleLU.h b/liboctave/SparsedbleLU.h new file mode 100644 --- /dev/null +++ b/liboctave/SparsedbleLU.h @@ -0,0 +1,62 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_LU_h) +#define octave_sparse_LU_h 1 + +#include "sparse-base-lu.h" +#include "dSparse.h" + +class +SparseLU : public sparse_base_lu +{ +public: + + SparseLU (void) + : sparse_base_lu () { } + + SparseLU (const SparseMatrix& a, double piv_thres = -1.0); + + SparseLU (const SparseMatrix& a, const ColumnVector& Qinit, + double piv_thres = -1.0, bool FixedQ = false); + + SparseLU (const SparseLU& a) + : sparse_base_lu (a) { } + + SparseLU& operator = (const SparseLU& a) + { + if (this != &a) + sparse_base_lu + :: operator = (a); + + return *this; + } + + ~SparseLU (void) { } +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/UMFPACK.README b/liboctave/UMFPACK.README new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK.README @@ -0,0 +1,47 @@ +This directory contains a modified copy of UMFPACKv4.4 in the +directory UMFPACK. The complete changes from the original version may +be found in the file UMFPACK.patch. + +UMFPACK was written by Timothy A. Davis (davis@cise.ufl.edu), +University of Florida. + +UMFPACK includes a modified version of COLAMD V2.0, by Stefan +I. Larimore and Timothy A. Davis, University of Florida. The COLAMD +algorithm was developed in collaboration with John Gilbert, Xerox Palo +Alto Research Center, and Esmond Ng, Lawrence Berkeley National +Laboratory. + +UMFPACK also includes AMD, by Timothy A. Davis, Patrick R. Amestoy, +and Iain S. Duff. + +UMFPACK Version 2.2.1 (MA38 in the Harwell Subroutine Library) is +co-authored with Iain S. Duff, Rutherford Appleton Laboratory. + +The copyright and license information is: + + UMFPACK Version 4.4 (Jan. 28, 2005), Copyright (c) 2005 by Timothy A. + Davis. All Rights Reserved. + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +John W. Eaton +jwe@bevo.che.wisc.edu +University of Wisconsin-Madison +Department of Chemical & Biological Engineering + +Wed Feb 01 22:15:20 2005 diff --git a/liboctave/UMFPACK.files b/liboctave/UMFPACK.files new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK.files @@ -0,0 +1,79 @@ + +# non-user-callable umf_*.[ch] files: +UMFCH := umf_assemble umf_blas3_update \ + umf_build_tuples umf_create_element \ + umf_dump umf_extend_front umf_garbage_collection \ + umf_get_memory umf_init_front umf_kernel \ + umf_kernel_init umf_kernel_wrapup \ + umf_local_search umf_lsolve umf_ltsolve \ + umf_mem_alloc_element umf_mem_alloc_head_block \ + umf_mem_alloc_tail_block umf_mem_free_tail_block \ + umf_mem_init_memoryspace \ + umf_report_vector umf_row_search umf_scale_column \ + umf_set_stats umf_solve umf_symbolic_usage umf_transpose \ + umf_tuple_lengths umf_usolve umf_utsolve umf_valid_numeric \ + umf_valid_symbolic umf_grow_front umf_start_front umf_2by2 \ + umf_store_lu umf_scale + +# non-user-callable umf_*.[ch] files, int/long versions only (no real/complex): +UMFINT := umf_analyze umf_apply_order umf_colamd umf_free umf_fsize \ + umf_is_permutation umf_malloc umf_realloc umf_report_perm \ + umf_singletons + +# non-user-callable and user-callable amd_*.[ch] files (int/long versions only): +AMD := amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ + amd_order amd_control amd_info amd_valid + +# non-user-callable, created from umf_ltsolve.c, umf_utsolve.c, +# umf_triplet.c, and umf_assemble.c , with int/long and real/complex versions: +UMF_CREATED := umf_lhsolve umf_uhsolve umf_triplet_map_nox \ + umf_triplet_nomap_x umf_triplet_nomap_nox umf_triplet_map_x \ + umf_assemble_fixq umf_store_lu_drop + +# non-user-callable, int/long and real/complex versions: +UMF := $(UMF_CREATED) $(UMFCH) + +# user-callable umfpack_*.[ch] files (int/long and real/complex): +UMFPACK := umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ + umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ + umfpack_get_symbolic umfpack_get_determinant umfpack_numeric \ + umfpack_qsymbolic umfpack_report_control umfpack_report_info \ + umfpack_report_matrix umfpack_report_numeric umfpack_report_perm \ + umfpack_report_status umfpack_report_symbolic umfpack_report_triplet \ + umfpack_report_vector umfpack_solve umfpack_symbolic \ + umfpack_transpose umfpack_triplet_to_col umfpack_scale \ + umfpack_load_numeric umfpack_save_numeric \ + umfpack_load_symbolic umfpack_save_symbolic + +# user-callable, created from umfpack_solve.c (umfpack_wsolve.h exists, though): +# with int/long and real/complex versions: +UMFPACKW := umfpack_wsolve + +USER := $(UMFPACKW) $(UMFPACK) + +# user-callable, only one version for int/long, real/complex, *.[ch] files: +GENERIC := umfpack_timer umfpack_tictoc + +UMFPACK_BASE := \ + $(subst umf_, umf_o_, $(UMFINT)) \ + $(subst umf_, umf_od_, $(UMF)) \ + $(subst umfpack_, umfpack_od_, $(USER)) \ + $(subst umf_, umf_oz_, $(UMF)) \ + $(subst umfpack_, umfpack_oz_, $(USER)) \ + $(subst amd_, amd_o_, $(AMD)) \ + $(subst umfpack_, umfpack_o_, $(GENERIC)) + +UMFPACK_OBJ := $(addsuffix .o, $(UMFPACK_BASE)) + +UMFPACK_PICOBJ := $(addprefix pic/, $(UMFPACK_OBJ)) + +UMFPACK_INCFLAGS := \ + -I$(top_srcdir)/liboctave/UMFPACK/UMFPACK/Include \ + -I$(top_srcdir)/liboctave/UMFPACK/UMFPACK/Source \ + -I$(top_srcdir)/liboctave/UMFPACK/AMD/Include \ + -I$(top_srcdir)/liboctave/UMFPACK/AMD/Source + +$(UMFPACK_OBJ) $(UMFPACK_PICOBJ): INCFLAGS += $(UMFPACK_INCFLAGS) + +UMFPACK_EXTRAS := UMFPACK.files UMFPACK.rules UMFPACK.patch UMFPACK.README + diff --git a/liboctave/UMFPACK.patch b/liboctave/UMFPACK.patch new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK.patch @@ -0,0 +1,4825 @@ +--- UMFPACKv4.4.orig/AMD/Makefile 2004-01-29 20:40:44.000000000 +0100 ++++ UMFPACK/AMD/Makefile 2005-02-01 22:00:38.917972334 +0100 +@@ -28,11 +28,18 @@ + ( cd Demo ; make cross ) + - cat Doc/License + ++# compile a Octave version ++# (not compiled by "make all") ++octave: ++ ( cd OCTAVE ; make ) ++ - cat Doc/License ++ + # remove object files, but keep the compiled programs and library archives + clean: + ( cd Source ; make clean ) + ( cd Demo ; make clean ) + ( cd MATLAB ; make clean ) ++ ( cd OCTAVE ; make clean ) + ( cd Doc ; make clean ) + + # clean, and then remove compiled programs and library archives +@@ -40,6 +47,7 @@ + ( cd Source ; make purge ) + ( cd Demo ; make purge ) + ( cd MATLAB ; make purge ) ++ ( cd OCTAVE ; make purge ) + ( cd Doc ; make purge ) + + # create PDF documents for the original distribution +--- UMFPACKv4.4.orig/UMFPACK/Makefile 2004-01-29 20:40:48.000000000 +0100 ++++ UMFPACK/UMFPACK/Makefile 2005-02-01 22:00:38.916972398 +0100 +@@ -32,12 +32,19 @@ + hb: + ( cd Demo ; make hb ) + ++# compile a Octave version ++# (not compiled by "make all") ++octave: ++ ( cd OCTAVE ; make ) ++ - cat Doc/License ++ + # remove object files, but keep the compiled programs and library archives + clean: + ( cd ../AMD ; make clean ) + ( cd Source ; make clean ) + ( cd Demo ; make clean ) + ( cd MATLAB ; make clean ) ++ ( cd OCTAVE ; make clean ) + ( cd Doc ; make clean ) + + # clean, and then remove compiled programs and library archives +@@ -46,6 +53,7 @@ + ( cd Source ; make purge ) + ( cd Demo ; make purge ) + ( cd MATLAB ; make purge ) ++ ( cd OCTAVE ; make purge ) + ( cd Doc ; make purge ) + + # create PDF documents for the original distribution +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/Contents.m UMFPACK/UMFPACK/OCTAVE/Contents.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/Contents.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/Contents.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,1 +1,22 @@ ++%Contents of the UMFPACK sparse matrix toolbox: ++% ++% umfpack computes x=A\b, x=A/b, or lu (A) for a sparse matrix A ++% umfpack_make to compile umfpack for use in MATLAB ++% umfpack_report prints optional control settings and statistics ++% umfpack_demo a long demo ++% umfpack_simple a simple demo ++% umfpack_btf factorize A using a block triangular form ++% umfpack_solve x = A\b or x = b/A ++% lu_normest estimates norm (L*U-A, 1) without forming L*U-A ++% luflop given L and U, computes # of flops required to compute them ++% ++% See also: ++% amd symmetric minimum degree ordering ++% colamd unsymmetric column approx minimum degree ordering ++% symamd symmetric approx minimum degree ordering, based on colamd ++% ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. Type umfpack_details for License. ++ ++help Contents +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/GNUmakefile 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/GNUmakefile 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,248 @@ ++#------------------------------------------------------------------------------- ++# UMFPACK GNUmakefile for the UMFPACK OCTAVE oct-file (GNU "make" only) ++#------------------------------------------------------------------------------- ++ ++.PRECIOUS: %.o ++ ++# UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++# Davis. All Rights Reserved. See ../README for License. ++ ++all: umfpack luflop ++ ++include ../Make/Make.include ++ ++MKOCT = mkoctfile $(CONFIG) -DNRECIPROCAL -I/usr/include/atlas -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source ++ ++OCT_SPARSE_INC = -I../../../ ++ ++ ++#------------------------------------------------------------------------------- ++# source files ++#------------------------------------------------------------------------------- ++ ++# non-user-callable umf_*.[ch] files: ++UMFCH = umf_assemble umf_blas3_update \ ++ umf_build_tuples umf_create_element \ ++ umf_dump umf_extend_front umf_garbage_collection \ ++ umf_get_memory umf_init_front umf_kernel \ ++ umf_kernel_init umf_kernel_wrapup \ ++ umf_local_search umf_lsolve umf_ltsolve \ ++ umf_mem_alloc_element umf_mem_alloc_head_block \ ++ umf_mem_alloc_tail_block umf_mem_free_tail_block \ ++ umf_mem_init_memoryspace \ ++ umf_report_vector umf_row_search umf_scale_column \ ++ umf_set_stats umf_solve umf_symbolic_usage umf_transpose \ ++ umf_tuple_lengths umf_usolve umf_utsolve umf_valid_numeric \ ++ umf_valid_symbolic umf_grow_front umf_start_front umf_2by2 \ ++ umf_store_lu umf_scale ++ ++# non-user-callable umf_*.[ch] files, int/long versions only (no real/complex): ++UMFINT = umf_analyze umf_apply_order umf_colamd umf_free umf_fsize \ ++ umf_is_permutation umf_malloc umf_realloc umf_report_perm \ ++ umf_singletons ++ ++# non-user-callable and user-callable amd_*.[ch] files (int/long versions only): ++AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ ++ amd_order amd_control amd_info amd_valid ++ ++# non-user-callable, created from umf_ltsolve.c, umf_utsolve.c, ++# umf_triplet.c, and umf_assemble.c , with int/long and real/complex versions: ++UMF_CREATED = umf_lhsolve umf_uhsolve umf_triplet_map_nox \ ++ umf_triplet_nomap_x umf_triplet_nomap_nox umf_triplet_map_x \ ++ umf_assemble_fixq umf_store_lu_drop ++ ++# non-user-callable, int/long and real/complex versions: ++UMF = $(UMF_CREATED) $(UMFCH) ++ ++# user-callable umfpack_*.[ch] files (int/long and real/complex): ++UMFPACK = umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ ++ umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ ++ umfpack_get_symbolic umfpack_get_determinant umfpack_numeric \ ++ umfpack_qsymbolic umfpack_report_control umfpack_report_info \ ++ umfpack_report_matrix umfpack_report_numeric umfpack_report_perm \ ++ umfpack_report_status umfpack_report_symbolic umfpack_report_triplet \ ++ umfpack_report_vector umfpack_solve umfpack_symbolic \ ++ umfpack_transpose umfpack_triplet_to_col umfpack_scale \ ++ umfpack_load_numeric umfpack_save_numeric \ ++ umfpack_load_symbolic umfpack_save_symbolic ++ ++# user-callable, created from umfpack_solve.c (umfpack_wsolve.h exists, though): ++# with int/long and real/complex versions: ++UMFPACKW = umfpack_wsolve ++ ++USER = $(UMFPACKW) $(UMFPACK) ++ ++# user-callable, only one version for int/long, real/complex, *.[ch] files: ++GENERIC = umfpack_timer umfpack_tictoc ++ ++#------------------------------------------------------------------------------- ++# include files: ++#------------------------------------------------------------------------------- ++ ++AMDH = ../../AMD/Source/amd_internal.h ../../AMD/Include/amd.h ++ ++INC1 = umf_config.h umf_version.h umf_internal.h umf_triplet.h ++ ++INC = ../Include/umfpack.h \ ++ $(addprefix ../Source/, $(INC1)) \ ++ $(addprefix ../Source/, $(addsuffix .h,$(UMFCH))) \ ++ $(addprefix ../Source/, $(addsuffix .h,$(UMFINT))) \ ++ $(addprefix ../Include/, $(addsuffix .h,$(USER))) \ ++ $(addprefix ../Include/, $(addsuffix .h,$(GENERIC))) \ ++ $(AMDH) ++ ++#------------------------------------------------------------------------------- ++# Create the umfpack and amd oct-file for OCTAVE (int versions only) ++#------------------------------------------------------------------------------- ++ ++OCTI = $(addsuffix .o, $(subst umf_,umf_o_,$(UMFINT))) ++OCTDI = $(addsuffix .o, $(subst umf_,umf_od_,$(UMF)) $(subst umfpack_,umfpack_od_,$(USER))) ++OCTZI = $(addsuffix .o, $(subst umf_,umf_oz_,$(UMF)) $(subst umfpack_,umfpack_oz_,$(USER)) ) ++OCTAMD = $(addsuffix .o, $(subst amd_,amd_o_,$(AMD))) ++OCTGN = $(addsuffix .o, $(subst umfpack_,umfpack_o_,$(GENERIC))) ++ ++OCTUMFPACK = $(OCTI) $(OCTDI) $(OCTZI) $(OCTGN) ++ ++OCTUMFPACK_LIB = umfpack_octave.o ++ ++# Note that mkoctfile has an "-o" option, but it doesn't work in conjunction ++# with the "-c" option, thus the need for $(MV) commands. ++# If it did, then the rules would be much simpler: ++# $(MKOCT) -DDINT -c $< -o $@ ++ ++#---------------------------------------- ++# integer-only routines (no real/complex): ++#---------------------------------------- ++ ++amd_o_%.o: ../../AMD/Source/amd_%.c $(AMDH) ++ $(MKOCT) -DDINT -c $< ++ - $(MV) ../../AMD/Source/amd_$*.o $@ ++ ++ ++umf_o_%.o: ../Source/umf_%.c $(INC) ++ $(MKOCT) -DDINT -c $< ++ - $(MV) ../Source/umf_$*.o $@ ++ ++#---------------------------------------- ++# Double precision, int version, for OCTAVE ++#---------------------------------------- ++ ++umf_od_%.o: ../Source/umf_%.c $(INC) ++ $(MKOCT) -DDINT -c $< ++ - $(MV) ../Source/umf_$*.o $@ ++ ++umf_od_%hsolve.o: ../Source/umf_%tsolve.c $(INC) ++ $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c $< ++ - $(MV) ../Source/umf_$*tsolve.o $@ ++ ++umf_od_triplet_map_x.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DDINT -DDO_MAP -DDO_VALUES -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_od_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DDINT -DDO_MAP -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_od_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DDINT -DDO_VALUES -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_od_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DDINT -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_od_assemble_fixq.o: ../Source/umf_assemble.c $(INC) ++ $(MKOCT) -DDINT -DFIXQ -c $< ++ - $(MV) ../Source/umf_assemble.o $@ ++ ++umf_od_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) ++ $(MKOCT) -DDINT -DDROP -c $< ++ - $(MV) ../Source/umf_store_lu.o $@ ++ ++umfpack_od_wsolve.o: ../Source/umfpack_solve.c $(INC) ++ $(MKOCT) -DDINT -DWSOLVE -c $< ++ - $(MV) ../Source/umfpack_solve.o $@ ++ ++umfpack_od_%.o: ../Source/umfpack_%.c $(INC) ++ $(MKOCT) -DDINT -c $< ++ - $(MV) ../Source/umfpack_$*.o $@ ++ ++#---------------------------------------- ++# Complex double precision, int version, for OCTAVE ++#---------------------------------------- ++ ++umf_oz_%.o: ../Source/umf_%.c $(INC) ++ $(MKOCT) -DZINT -c $< ++ - $(MV) ../Source/umf_$*.o $@ ++ ++umf_oz_%hsolve.o: ../Source/umf_%tsolve.c $(INC) ++ $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c $< ++ - $(MV) ../Source/umf_$*tsolve.o $@ ++ ++umf_oz_triplet_map_x.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DZINT -DDO_MAP -DDO_VALUES -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_oz_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DZINT -DDO_MAP -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_oz_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DZINT -DDO_VALUES -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_oz_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) ++ $(MKOCT) -DZINT -c $< ++ - $(MV) ../Source/umf_triplet.o $@ ++ ++umf_oz_assemble_fixq.o: ../Source/umf_assemble.c $(INC) ++ $(MKOCT) -DZINT -DFIXQ -c $< ++ - $(MV) ../Source/umf_assemble.o $@ ++ ++umf_oz_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) ++ $(MKOCT) -DZINT -DDROP -c $< ++ - $(MV) ../Source/umf_store_lu.o $@ ++ ++umfpack_oz_wsolve.o: ../Source/umfpack_solve.c $(INC) ++ $(MKOCT) -DZINT -DWSOLVE -c $< ++ - $(MV) ../Source/umfpack_solve.o $@ ++ ++umfpack_oz_%.o: ../Source/umfpack_%.c $(INC) ++ $(MKOCT) -DZINT -c $< ++ - $(MV) ../Source/umfpack_$*.o $@ ++ ++#---------------------------------------- ++# Generic routines for OCTAVE ++#---------------------------------------- ++ ++umfpack_o_timer.o: ../Source/umfpack_timer.c $(INC) ++ $(MKOCT) -c $< ++ - $(MV) ../Source/umfpack_timer.o $@ ++ ++umfpack_o_tictoc.o: ../Source/umfpack_tictoc.c $(INC) ++ $(MKOCT) -c $< ++ - $(MV) ../Source/umfpack_tictoc.o $@ ++ ++#---------------------------------------- ++# umfpack oct-files ++#---------------------------------------- ++ ++umfpack: umfpack.cc $(OCTUMFPACK) $(OCTAMD) ++ $(MKOCT) $(OCT_SPARSE_INC) umfpack.cc $(OCTUMFPACK) $(OCTAMD) -o umfpack.oct ++ ++luflop: luflop.cc ++ $(MKOCT) $(OCT_SPARSE_INC) luflop.cc -o luflop.oct ++ ++#---------------------------------------- ++# umfpack library to link with octave ++#---------------------------------------- ++ ++octave: $(OCTUMFPACK) $(OCTAMD) ++ ld -r $(OCTUMFPACK) $(OCTAMD) -o ../../../$(OCTUMFPACK_LIB) ++ ++#------------------------------------------------------------------------------- ++# Remove all but the files in the original distribution ++#------------------------------------------------------------------------------- ++ ++purge: clean ++ - $(RM) *.oct *.so +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/luflop.cc UMFPACK/UMFPACK/OCTAVE/luflop.cc +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/luflop.cc 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/luflop.cc 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,223 @@ ++/* ++ ++Copyright (C) 2004 David Bateman ++ ++This program is free software; you can redistribute it and/or modify it ++under the terms of the GNU General Public License as published by the ++Free Software Foundation; either version 2, or (at your option) any ++later version. ++ ++This program is distributed in the hope that it will be useful, but WITHOUT ++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; see the file COPYING. If not, write to the Free ++Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++In addition to the terms of the GPL, you are permitted to link ++this program with any Open Source program, as defined by the ++Open Source Initiative (www.opensource.org) ++ ++*/ ++ ++/* ++ ++This is the Octave interface to the UMFPACK code, which bore the following ++copyright ++ ++ UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++ Davis. All Rights Reserved. See ../README for License. ++ email: davis@cise.ufl.edu CISE Department, Univ. of Florida. ++ web: http://www.cise.ufl.edu/research/sparse/umfpack ++ ++*/ ++ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ov-re-sparse.h" ++#include "ov-cx-sparse.h" ++ ++DEFUN_DLD (luflop, args, nargout, ++ "-*- texinfo -*-\n\ ++@deftypefn {Loadable Function} {@var{f} =} luflup (@var{l}, @var{u})\n\ ++\n\ ++Given an LU factorization, compute how many flops took to compute it. This\n\ ++is the same as (assuming U has a zero-free diagonal):\n\ ++\n\ ++@example\n\ ++@group\n\ ++ Lnz = full (sum (spones (L))) - 1 ;\n\ ++ Unz = full (sum (spones (U')))' - 1 ;\n\ ++ f = 2*Lnz*Unz + sum (Lnz) ;\n\ ++@end group\n\ ++@end example\n\ ++\n\ ++except that no extra workspace is allocated for spones (L) and spones (U).\n\ ++L and U must be sparse.\n\ ++\n\ ++Note: the above expression has a subtle undercount when exact numerical\n\ ++cancelation occurs. Try [L,U,P] = lu (sparse (ones (10))) and then\n\ ++luflop (L,U).\n\ ++@end deftypefn") ++{ ++ int nargin = args.length (); ++ octave_value retval; ++ ++ // These are here only so that the C++ destructors don't prematurally ++ // remove the underlying data we are interested in ++ SparseMatrix Lmatrix, Umatrix; ++ SparseComplexMatrix CLmatrix, CUmatrix; ++ int *Lp, *Li, *Up, *Ui; ++ int Lm, Ln, Um, Un; ++ ++ if (nargin != 2) ++ { ++ usage ("f = luflop (L, U)"); ++ return retval; ++ } ++ ++ if (args(0).class_name () == "sparse") ++ { ++ if (args(0).is_complex_type ()) ++ { ++ CLmatrix = ++ (((const octave_sparse_complex_matrix&) args(0).get_rep ()) ++ .sparse_complex_matrix_value ()); ++ Lp = CLmatrix.cidx (); ++ Li = CLmatrix.ridx (); ++ Lm = CLmatrix.rows (); ++ Ln = CLmatrix.cols (); ++ } ++ else ++ { ++ Lmatrix = (((const octave_sparse_matrix&) args(0).get_rep ()) ++ .sparse_matrix_value ()); ++ Lp = Lmatrix.cidx (); ++ Li = Lmatrix.ridx (); ++ Lm = Lmatrix.rows (); ++ Ln = Lmatrix.cols (); ++ } ++ } ++ else ++ { ++ if (args(0).is_complex_type ()) ++ { ++ CLmatrix = SparseComplexMatrix (args(0).complex_matrix_value ()); ++ Lp = CLmatrix.cidx (); ++ Li = CLmatrix.ridx (); ++ Lm = CLmatrix.rows (); ++ Ln = CLmatrix.cols (); ++ } ++ else ++ { ++ Lmatrix = SparseMatrix (args(0).matrix_value ()); ++ Lp = Lmatrix.cidx (); ++ Li = Lmatrix.ridx (); ++ Lm = Lmatrix.rows (); ++ Ln = Lmatrix.cols (); ++ } ++ } ++ ++ ++ if (args(0).class_name () == "sparse") ++ { ++ if (args(1).is_complex_type ()) ++ { ++ CUmatrix = ++ (((const octave_sparse_complex_matrix&) args(1).get_rep ()) ++ .sparse_complex_matrix_value ()); ++ Up = CUmatrix.cidx (); ++ Ui = CUmatrix.ridx (); ++ Um = CUmatrix.rows (); ++ Un = CUmatrix.cols (); ++ } ++ else ++ { ++ Umatrix = ++ (((const octave_sparse_matrix&) args(1).get_rep ()) ++ .sparse_matrix_value ()); ++ Up = Umatrix.cidx (); ++ Ui = Umatrix.ridx (); ++ Um = Umatrix.rows (); ++ Un = Umatrix.cols (); ++ } ++ } ++ else ++ { ++ if (args(1).is_complex_type ()) ++ { ++ CUmatrix = SparseComplexMatrix (args(1).complex_matrix_value ()); ++ Up = CUmatrix.cidx (); ++ Ui = CUmatrix.ridx (); ++ Um = CUmatrix.rows (); ++ Un = CUmatrix.cols (); ++ } ++ else ++ { ++ Umatrix = SparseMatrix (args(1).matrix_value ()); ++ Up = Umatrix.cidx (); ++ Ui = Umatrix.ridx (); ++ Um = Umatrix.rows (); ++ Un = Umatrix.cols (); ++ } ++ } ++ ++ ++ if (error_state) ++ return retval; ++ ++ ++ int n = Lm; ++ ++ if (n != Ln || n != Um || n != Un) ++ error ("luflop: L and U must be square"); ++ else ++ { ++ ++ OCTAVE_LOCAL_BUFFER (int, Unz, n); ++ ++ // count the nonzeros in each row of U ++ for (int row = 0 ; row < n ; row++) ++ Unz [row] = 0 ; ++ ++ for (int col = 0 ; col < n ; col++) ++ { ++ for (int p = Up [col] ; p < Up [col+1] ; p++) ++ { ++ int row = Ui [p] ; ++ Unz [row]++ ; ++ } ++ } ++ ++ // count the flops ++ double flop_count = 0.0 ; ++ for (int k = 0 ; k < n ; k++) ++ { ++ /* off-diagonal nonzeros in column k of L: */ ++ int Lnz_k = Lp [k+1] - Lp [k] - 1 ; ++ int Unz_k = Unz [k] - 1 ; ++ flop_count += (2 * Lnz_k * Unz_k) + Lnz_k ; ++ } ++ ++ // return the result ++ retval = flop_count; ++ } ++ ++ return retval; ++} ++ ++/* ++;;; Local Variables: *** ++;;; mode: C++ *** ++;;; End: *** ++*/ +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/lu_normest.m UMFPACK/UMFPACK/OCTAVE/lu_normest.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/lu_normest.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/lu_normest.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,106 @@ ++function rho = lu_normest (A, L, U) ++% LU_NORMEST: estimate the 1-norm of A-L*U without computing L*U ++% ++% Usage: ++% ++% rho = lu_normest (A, L, U) ++% ++% which estimates the computation of the 1-norm: ++% ++% rho = norm (A-L*U, 1) ++% ++% Authors: William W. Hager, Math Dept., Univ. of Florida ++% Timothy A. Davis, CISE Dept., Univ. of Florida ++% Gainesville, FL, 32611, USA. ++% based on normest1, contributed on November, 1997 ++% ++% This code can be quite easily adapted to estimate the 1-norm of any ++% matrix E, where E itself is dense or not explicitly represented, but the ++% computation of E (and E') times a vector is easy. In this case, our matrix ++% of interest is: ++% ++% E = A-L*U ++% ++% That is, L*U is the LU factorization of A, where A, L and U ++% are sparse. This code works for dense matrices A and L too, ++% but it would not be needed in that case, since E is easy to compute ++% explicitly. For sparse A, L, and U, computing E explicitly would be quite ++% expensive, and thus normest (A-L*U) would be prohibitive. ++% ++% For a detailed description, see Davis, T. A. and Hager, W. W., ++% Modifying a sparse Cholesky factorization, SIAM J. Matrix Analysis and ++% Applications, 1999, vol. 20, no. 3, 606-627. ++ ++% The three places that the matrix-vector multiply E*x is used are highlighted. ++% Note that E is never formed explicity. ++ ++[m n] = size (A) ; ++ ++if (m ~= n) ++ % pad A, L, and U with zeros so that they are all square ++ if (m < n) ++ U = [ U ; (sparse (n-m,n)) ] ; ++ L = [ L , (sparse (m,n-m)) ; (sparse (n-m,n)) ] ; ++ A = [ A ; (sparse (n-m,n)) ] ; ++ else ++ U = [ U , (sparse (n,m-n)) ; (sparse (m-n,m)) ] ; ++ L = [ L , (sparse (m,m-n)) ] ; ++ A = [ A , (sparse (m,m-n)) ] ; ++ end ++end ++ ++[m n] = size (A) ; ++ ++notvisited = ones (m, 1) ; % nonvisited(j) is zero if j is visited, 1 otherwise ++rho = 0 ; % the global rho ++ ++At = A' ; ++Lt = L' ; ++ ++for trial = 1:3 % { ++ ++ x = notvisited ./ sum (notvisited) ; ++ rho1 = 0 ; % the current rho for this trial ++ ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ Ex1 = (A*x) - L*(U*x) ; ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ ++ rho2 = norm (Ex1, 1) ; ++ ++ while rho2 > rho1 % { ++ ++ rho1 = rho2 ; ++ y = 2*(Ex1 >= 0) - 1 ; ++ ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%% COMPUTE z = E'*y EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ z = (A'*y) - U'*(L'*y) ; ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ ++ [zj, j] = max (abs (z .* notvisited)) ; ++ j = j (1) ; ++ if (abs (z (j)) > z'*x) % { ++ x = zeros (m, 1) ; ++ x (j) = 1 ; ++ notvisited (j) = 0 ; ++ else % } { ++ break ; ++ end % } ++ ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ Ex1 = (A*x) - L*(U*x) ; ++ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++ ++ rho2 = norm (Ex1, 1) ; ++ ++ end % } ++ ++ rho = max (rho, rho1) ; ++ ++end % } +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/Makefile UMFPACK/UMFPACK/OCTAVE/Makefile +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/Makefile 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,517 @@ ++#------------------------------------------------------------------------------- ++# UMFPACK Makefile for the UMFPACK MATLAB mexFunction (old "make" only) ++#------------------------------------------------------------------------------- ++ ++# UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++# Davis. All Rights Reserved. See ../README for License. ++ ++# This is a very ugly Makefile, and is only provided for those who do not ++# have GNU make. Note that it is not used if you have GNU make. It ignores ++# dependency checking and just compiles everything. It was created ++# automatically, via make -n using the GNUmakefile. That way, I don't have ++# maintain two Makefiles. ++ ++all: umfpack luflop ++ ++include ../Make/Make.include ++ ++MKOCT = mkoctfile $(CONFIG) -DNRECIPROCAL -I/usr/include/atlas -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source ++ ++OCT_SPARSE_INC = -I../../../ ++OCTUMFPACK_LIB = umfpack_octave.o ++ ++umfpack: ++ $(MKOCT) -DDINT -c ../Source/umf_analyze.c ++ $(MV) -f ../Source/umf_analyze.o umf_m_analyze.o ++ $(MKOCT) -DDINT -c ../Source/umf_apply_order.c ++ $(MV) -f ../Source/umf_apply_order.o umf_m_apply_order.o ++ $(MKOCT) -DDINT -c ../Source/umf_colamd.c ++ $(MV) -f ../Source/umf_colamd.o umf_m_colamd.o ++ $(MKOCT) -DDINT -c ../Source/umf_free.c ++ $(MV) -f ../Source/umf_free.o umf_m_free.o ++ $(MKOCT) -DDINT -c ../Source/umf_fsize.c ++ $(MV) -f ../Source/umf_fsize.o umf_m_fsize.o ++ $(MKOCT) -DDINT -c ../Source/umf_is_permutation.c ++ $(MV) -f ../Source/umf_is_permutation.o umf_m_is_permutation.o ++ $(MKOCT) -DDINT -c ../Source/umf_malloc.c ++ $(MV) -f ../Source/umf_malloc.o umf_m_malloc.o ++ $(MKOCT) -DDINT -c ../Source/umf_realloc.c ++ $(MV) -f ../Source/umf_realloc.o umf_m_realloc.o ++ $(MKOCT) -DDINT -c ../Source/umf_report_perm.c ++ $(MV) -f ../Source/umf_report_perm.o umf_m_report_perm.o ++ $(MKOCT) -DDINT -c ../Source/umf_singletons.c ++ $(MV) -f ../Source/umf_singletons.o umf_m_singletons.o ++ $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c ++ $(MV) -f ../Source/umf_ltsolve.o umf_od_lhsolve.o ++ $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c ++ $(MV) -f ../Source/umf_utsolve.o umf_od_uhsolve.o ++ $(MKOCT) -DDINT -DDO_MAP -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_od_triplet_map_nox.o ++ $(MKOCT) -DDINT -DDO_VALUES -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_od_triplet_nomap_x.o ++ $(MKOCT) -DDINT -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_od_triplet_nomap_nox.o ++ $(MKOCT) -DDINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_od_triplet_map_x.o ++ $(MKOCT) -DDINT -DFIXQ -c ../Source/umf_assemble.c ++ $(MV) -f ../Source/umf_assemble.o umf_od_assemble_fixq.o ++ $(MKOCT) -DDINT -DDROP -c ../Source/umf_store_lu.c ++ $(MV) -f ../Source/umf_store_lu.o umf_od_store_lu_drop.o ++ $(MKOCT) -DDINT -c ../Source/umf_assemble.c ++ $(MV) -f ../Source/umf_assemble.o umf_od_assemble.o ++ $(MKOCT) -DDINT -c ../Source/umf_blas3_update.c ++ $(MV) -f ../Source/umf_blas3_update.o umf_od_blas3_update.o ++ $(MKOCT) -DDINT -c ../Source/umf_build_tuples.c ++ $(MV) -f ../Source/umf_build_tuples.o umf_od_build_tuples.o ++ $(MKOCT) -DDINT -c ../Source/umf_create_element.c ++ $(MV) -f ../Source/umf_create_element.o umf_od_create_element.o ++ $(MKOCT) -DDINT -c ../Source/umf_dump.c ++ $(MV) -f ../Source/umf_dump.o umf_od_dump.o ++ $(MKOCT) -DDINT -c ../Source/umf_extend_front.c ++ $(MV) -f ../Source/umf_extend_front.o umf_od_extend_front.o ++ $(MKOCT) -DDINT -c ../Source/umf_garbage_collection.c ++ $(MV) -f ../Source/umf_garbage_collection.o umf_od_garbage_collection.o ++ $(MKOCT) -DDINT -c ../Source/umf_get_memory.c ++ $(MV) -f ../Source/umf_get_memory.o umf_od_get_memory.o ++ $(MKOCT) -DDINT -c ../Source/umf_init_front.c ++ $(MV) -f ../Source/umf_init_front.o umf_od_init_front.o ++ $(MKOCT) -DDINT -c ../Source/umf_kernel.c ++ $(MV) -f ../Source/umf_kernel.o umf_od_kernel.o ++ $(MKOCT) -DDINT -c ../Source/umf_kernel_init.c ++ $(MV) -f ../Source/umf_kernel_init.o umf_od_kernel_init.o ++ $(MKOCT) -DDINT -c ../Source/umf_kernel_wrapup.c ++ $(MV) -f ../Source/umf_kernel_wrapup.o umf_od_kernel_wrapup.o ++ $(MKOCT) -DDINT -c ../Source/umf_local_search.c ++ $(MV) -f ../Source/umf_local_search.o umf_od_local_search.o ++ $(MKOCT) -DDINT -c ../Source/umf_lsolve.c ++ $(MV) -f ../Source/umf_lsolve.o umf_od_lsolve.o ++ $(MKOCT) -DDINT -c ../Source/umf_ltsolve.c ++ $(MV) -f ../Source/umf_ltsolve.o umf_od_ltsolve.o ++ $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_element.c ++ $(MV) -f ../Source/umf_mem_alloc_element.o umf_od_mem_alloc_element.o ++ $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_head_block.c ++ $(MV) -f ../Source/umf_mem_alloc_head_block.o umf_od_mem_alloc_head_block.o ++ $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_tail_block.c ++ $(MV) -f ../Source/umf_mem_alloc_tail_block.o umf_od_mem_alloc_tail_block.o ++ $(MKOCT) -DDINT -c ../Source/umf_mem_free_tail_block.c ++ $(MV) -f ../Source/umf_mem_free_tail_block.o umf_od_mem_free_tail_block.o ++ $(MKOCT) -DDINT -c ../Source/umf_mem_init_memoryspace.c ++ $(MV) -f ../Source/umf_mem_init_memoryspace.o umf_od_mem_init_memoryspace.o ++ $(MKOCT) -DDINT -c ../Source/umf_report_vector.c ++ $(MV) -f ../Source/umf_report_vector.o umf_od_report_vector.o ++ $(MKOCT) -DDINT -c ../Source/umf_row_search.c ++ $(MV) -f ../Source/umf_row_search.o umf_od_row_search.o ++ $(MKOCT) -DDINT -c ../Source/umf_scale_column.c ++ $(MV) -f ../Source/umf_scale_column.o umf_od_scale_column.o ++ $(MKOCT) -DDINT -c ../Source/umf_set_stats.c ++ $(MV) -f ../Source/umf_set_stats.o umf_od_set_stats.o ++ $(MKOCT) -DDINT -c ../Source/umf_solve.c ++ $(MV) -f ../Source/umf_solve.o umf_od_solve.o ++ $(MKOCT) -DDINT -c ../Source/umf_symbolic_usage.c ++ $(MV) -f ../Source/umf_symbolic_usage.o umf_od_symbolic_usage.o ++ $(MKOCT) -DDINT -c ../Source/umf_transpose.c ++ $(MV) -f ../Source/umf_transpose.o umf_od_transpose.o ++ $(MKOCT) -DDINT -c ../Source/umf_tuple_lengths.c ++ $(MV) -f ../Source/umf_tuple_lengths.o umf_od_tuple_lengths.o ++ $(MKOCT) -DDINT -c ../Source/umf_usolve.c ++ $(MV) -f ../Source/umf_usolve.o umf_od_usolve.o ++ $(MKOCT) -DDINT -c ../Source/umf_utsolve.c ++ $(MV) -f ../Source/umf_utsolve.o umf_od_utsolve.o ++ $(MKOCT) -DDINT -c ../Source/umf_valid_numeric.c ++ $(MV) -f ../Source/umf_valid_numeric.o umf_od_valid_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umf_valid_symbolic.c ++ $(MV) -f ../Source/umf_valid_symbolic.o umf_od_valid_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umf_grow_front.c ++ $(MV) -f ../Source/umf_grow_front.o umf_od_grow_front.o ++ $(MKOCT) -DDINT -c ../Source/umf_start_front.c ++ $(MV) -f ../Source/umf_start_front.o umf_od_start_front.o ++ $(MKOCT) -DDINT -c ../Source/umf_2by2.c ++ $(MV) -f ../Source/umf_2by2.o umf_od_2by2.o ++ $(MKOCT) -DDINT -c ../Source/umf_store_lu.c ++ $(MV) -f ../Source/umf_store_lu.o umf_od_store_lu.o ++ $(MKOCT) -DDINT -c ../Source/umf_scale.c ++ $(MV) -f ../Source/umf_scale.o umf_od_scale.o ++ $(MKOCT) -DDINT -DWSOLVE -c ../Source/umfpack_solve.c ++ $(MV) -f ../Source/umfpack_solve.o umfpack_od_wsolve.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_col_to_triplet.c ++ $(MV) -f ../Source/umfpack_col_to_triplet.o umfpack_od_col_to_triplet.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_defaults.c ++ $(MV) -f ../Source/umfpack_defaults.o umfpack_od_defaults.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_free_numeric.c ++ $(MV) -f ../Source/umfpack_free_numeric.o umfpack_od_free_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_free_symbolic.c ++ $(MV) -f ../Source/umfpack_free_symbolic.o umfpack_od_free_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_get_numeric.c ++ $(MV) -f ../Source/umfpack_get_numeric.o umfpack_od_get_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_get_lunz.c ++ $(MV) -f ../Source/umfpack_get_lunz.o umfpack_od_get_lunz.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_get_symbolic.c ++ $(MV) -f ../Source/umfpack_get_symbolic.o umfpack_od_get_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_get_determinant.c ++ $(MV) -f ../Source/umfpack_get_determinant.o umfpack_od_get_determinant.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_numeric.c ++ $(MV) -f ../Source/umfpack_numeric.o umfpack_od_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_qsymbolic.c ++ $(MV) -f ../Source/umfpack_qsymbolic.o umfpack_od_qsymbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_control.c ++ $(MV) -f ../Source/umfpack_report_control.o umfpack_od_report_control.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_info.c ++ $(MV) -f ../Source/umfpack_report_info.o umfpack_od_report_info.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_matrix.c ++ $(MV) -f ../Source/umfpack_report_matrix.o umfpack_od_report_matrix.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_numeric.c ++ $(MV) -f ../Source/umfpack_report_numeric.o umfpack_od_report_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_perm.c ++ $(MV) -f ../Source/umfpack_report_perm.o umfpack_od_report_perm.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_status.c ++ $(MV) -f ../Source/umfpack_report_status.o umfpack_od_report_status.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_symbolic.c ++ $(MV) -f ../Source/umfpack_report_symbolic.o umfpack_od_report_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_triplet.c ++ $(MV) -f ../Source/umfpack_report_triplet.o umfpack_od_report_triplet.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_report_vector.c ++ $(MV) -f ../Source/umfpack_report_vector.o umfpack_od_report_vector.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_solve.c ++ $(MV) -f ../Source/umfpack_solve.o umfpack_od_solve.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_symbolic.c ++ $(MV) -f ../Source/umfpack_symbolic.o umfpack_od_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_transpose.c ++ $(MV) -f ../Source/umfpack_transpose.o umfpack_od_transpose.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_triplet_to_col.c ++ $(MV) -f ../Source/umfpack_triplet_to_col.o umfpack_od_triplet_to_col.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_scale.c ++ $(MV) -f ../Source/umfpack_scale.o umfpack_od_scale.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_load_numeric.c ++ $(MV) -f ../Source/umfpack_load_numeric.o umfpack_od_load_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_save_numeric.c ++ $(MV) -f ../Source/umfpack_save_numeric.o umfpack_od_save_numeric.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_load_symbolic.c ++ $(MV) -f ../Source/umfpack_load_symbolic.o umfpack_od_load_symbolic.o ++ $(MKOCT) -DDINT -c ../Source/umfpack_save_symbolic.c ++ $(MV) -f ../Source/umfpack_save_symbolic.o umfpack_od_save_symbolic.o ++ $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c ++ $(MV) -f ../Source/umf_ltsolve.o umf_oz_lhsolve.o ++ $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c ++ $(MV) -f ../Source/umf_utsolve.o umf_oz_uhsolve.o ++ $(MKOCT) -DZINT -DDO_MAP -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_map_nox.o ++ $(MKOCT) -DZINT -DDO_VALUES -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_nomap_x.o ++ $(MKOCT) -DZINT -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_nomap_nox.o ++ $(MKOCT) -DZINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c ++ $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_map_x.o ++ $(MKOCT) -DZINT -DFIXQ -c ../Source/umf_assemble.c ++ $(MV) -f ../Source/umf_assemble.o umf_oz_assemble_fixq.o ++ $(MKOCT) -DZINT -DDROP -c ../Source/umf_store_lu.c ++ $(MV) -f ../Source/umf_store_lu.o umf_oz_store_lu_drop.o ++ $(MKOCT) -DZINT -c ../Source/umf_assemble.c ++ $(MV) -f ../Source/umf_assemble.o umf_oz_assemble.o ++ $(MKOCT) -DZINT -c ../Source/umf_blas3_update.c ++ $(MV) -f ../Source/umf_blas3_update.o umf_oz_blas3_update.o ++ $(MKOCT) -DZINT -c ../Source/umf_build_tuples.c ++ $(MV) -f ../Source/umf_build_tuples.o umf_oz_build_tuples.o ++ $(MKOCT) -DZINT -c ../Source/umf_create_element.c ++ $(MV) -f ../Source/umf_create_element.o umf_oz_create_element.o ++ $(MKOCT) -DZINT -c ../Source/umf_dump.c ++ $(MV) -f ../Source/umf_dump.o umf_oz_dump.o ++ $(MKOCT) -DZINT -c ../Source/umf_extend_front.c ++ $(MV) -f ../Source/umf_extend_front.o umf_oz_extend_front.o ++ $(MKOCT) -DZINT -c ../Source/umf_garbage_collection.c ++ $(MV) -f ../Source/umf_garbage_collection.o umf_oz_garbage_collection.o ++ $(MKOCT) -DZINT -c ../Source/umf_get_memory.c ++ $(MV) -f ../Source/umf_get_memory.o umf_oz_get_memory.o ++ $(MKOCT) -DZINT -c ../Source/umf_init_front.c ++ $(MV) -f ../Source/umf_init_front.o umf_oz_init_front.o ++ $(MKOCT) -DZINT -c ../Source/umf_kernel.c ++ $(MV) -f ../Source/umf_kernel.o umf_oz_kernel.o ++ $(MKOCT) -DZINT -c ../Source/umf_kernel_init.c ++ $(MV) -f ../Source/umf_kernel_init.o umf_oz_kernel_init.o ++ $(MKOCT) -DZINT -c ../Source/umf_kernel_wrapup.c ++ $(MV) -f ../Source/umf_kernel_wrapup.o umf_oz_kernel_wrapup.o ++ $(MKOCT) -DZINT -c ../Source/umf_local_search.c ++ $(MV) -f ../Source/umf_local_search.o umf_oz_local_search.o ++ $(MKOCT) -DZINT -c ../Source/umf_lsolve.c ++ $(MV) -f ../Source/umf_lsolve.o umf_oz_lsolve.o ++ $(MKOCT) -DZINT -c ../Source/umf_ltsolve.c ++ $(MV) -f ../Source/umf_ltsolve.o umf_oz_ltsolve.o ++ $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_element.c ++ $(MV) -f ../Source/umf_mem_alloc_element.o umf_oz_mem_alloc_element.o ++ $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_head_block.c ++ $(MV) -f ../Source/umf_mem_alloc_head_block.o umf_oz_mem_alloc_head_block.o ++ $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_tail_block.c ++ $(MV) -f ../Source/umf_mem_alloc_tail_block.o umf_oz_mem_alloc_tail_block.o ++ $(MKOCT) -DZINT -c ../Source/umf_mem_free_tail_block.c ++ $(MV) -f ../Source/umf_mem_free_tail_block.o umf_oz_mem_free_tail_block.o ++ $(MKOCT) -DZINT -c ../Source/umf_mem_init_memoryspace.c ++ $(MV) -f ../Source/umf_mem_init_memoryspace.o umf_oz_mem_init_memoryspace.o ++ $(MKOCT) -DZINT -c ../Source/umf_report_vector.c ++ $(MV) -f ../Source/umf_report_vector.o umf_oz_report_vector.o ++ $(MKOCT) -DZINT -c ../Source/umf_row_search.c ++ $(MV) -f ../Source/umf_row_search.o umf_oz_row_search.o ++ $(MKOCT) -DZINT -c ../Source/umf_scale_column.c ++ $(MV) -f ../Source/umf_scale_column.o umf_oz_scale_column.o ++ $(MKOCT) -DZINT -c ../Source/umf_set_stats.c ++ $(MV) -f ../Source/umf_set_stats.o umf_oz_set_stats.o ++ $(MKOCT) -DZINT -c ../Source/umf_solve.c ++ $(MV) -f ../Source/umf_solve.o umf_oz_solve.o ++ $(MKOCT) -DZINT -c ../Source/umf_symbolic_usage.c ++ $(MV) -f ../Source/umf_symbolic_usage.o umf_oz_symbolic_usage.o ++ $(MKOCT) -DZINT -c ../Source/umf_transpose.c ++ $(MV) -f ../Source/umf_transpose.o umf_oz_transpose.o ++ $(MKOCT) -DZINT -c ../Source/umf_tuple_lengths.c ++ $(MV) -f ../Source/umf_tuple_lengths.o umf_oz_tuple_lengths.o ++ $(MKOCT) -DZINT -c ../Source/umf_usolve.c ++ $(MV) -f ../Source/umf_usolve.o umf_oz_usolve.o ++ $(MKOCT) -DZINT -c ../Source/umf_utsolve.c ++ $(MV) -f ../Source/umf_utsolve.o umf_oz_utsolve.o ++ $(MKOCT) -DZINT -c ../Source/umf_valid_numeric.c ++ $(MV) -f ../Source/umf_valid_numeric.o umf_oz_valid_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umf_valid_symbolic.c ++ $(MV) -f ../Source/umf_valid_symbolic.o umf_oz_valid_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umf_grow_front.c ++ $(MV) -f ../Source/umf_grow_front.o umf_oz_grow_front.o ++ $(MKOCT) -DZINT -c ../Source/umf_start_front.c ++ $(MV) -f ../Source/umf_start_front.o umf_oz_start_front.o ++ $(MKOCT) -DZINT -c ../Source/umf_2by2.c ++ $(MV) -f ../Source/umf_2by2.o umf_oz_2by2.o ++ $(MKOCT) -DZINT -c ../Source/umf_store_lu.c ++ $(MV) -f ../Source/umf_store_lu.o umf_oz_store_lu.o ++ $(MKOCT) -DZINT -c ../Source/umf_scale.c ++ $(MV) -f ../Source/umf_scale.o umf_oz_scale.o ++ $(MKOCT) -DZINT -DWSOLVE -c ../Source/umfpack_solve.c ++ $(MV) -f ../Source/umfpack_solve.o umfpack_oz_wsolve.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_col_to_triplet.c ++ $(MV) -f ../Source/umfpack_col_to_triplet.o umfpack_oz_col_to_triplet.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_defaults.c ++ $(MV) -f ../Source/umfpack_defaults.o umfpack_oz_defaults.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_free_numeric.c ++ $(MV) -f ../Source/umfpack_free_numeric.o umfpack_oz_free_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_free_symbolic.c ++ $(MV) -f ../Source/umfpack_free_symbolic.o umfpack_oz_free_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_get_numeric.c ++ $(MV) -f ../Source/umfpack_get_numeric.o umfpack_oz_get_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_get_lunz.c ++ $(MV) -f ../Source/umfpack_get_lunz.o umfpack_oz_get_lunz.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_get_symbolic.c ++ $(MV) -f ../Source/umfpack_get_symbolic.o umfpack_oz_get_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_get_determinant.c ++ $(MV) -f ../Source/umfpack_get_determinant.o umfpack_oz_get_determinant.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_numeric.c ++ $(MV) -f ../Source/umfpack_numeric.o umfpack_oz_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_qsymbolic.c ++ $(MV) -f ../Source/umfpack_qsymbolic.o umfpack_oz_qsymbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_control.c ++ $(MV) -f ../Source/umfpack_report_control.o umfpack_oz_report_control.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_info.c ++ $(MV) -f ../Source/umfpack_report_info.o umfpack_oz_report_info.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_matrix.c ++ $(MV) -f ../Source/umfpack_report_matrix.o umfpack_oz_report_matrix.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_numeric.c ++ $(MV) -f ../Source/umfpack_report_numeric.o umfpack_oz_report_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_perm.c ++ $(MV) -f ../Source/umfpack_report_perm.o umfpack_oz_report_perm.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_status.c ++ $(MV) -f ../Source/umfpack_report_status.o umfpack_oz_report_status.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_symbolic.c ++ $(MV) -f ../Source/umfpack_report_symbolic.o umfpack_oz_report_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_triplet.c ++ $(MV) -f ../Source/umfpack_report_triplet.o umfpack_oz_report_triplet.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_report_vector.c ++ $(MV) -f ../Source/umfpack_report_vector.o umfpack_oz_report_vector.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_solve.c ++ $(MV) -f ../Source/umfpack_solve.o umfpack_oz_solve.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_symbolic.c ++ $(MV) -f ../Source/umfpack_symbolic.o umfpack_oz_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_transpose.c ++ $(MV) -f ../Source/umfpack_transpose.o umfpack_oz_transpose.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_triplet_to_col.c ++ $(MV) -f ../Source/umfpack_triplet_to_col.o umfpack_oz_triplet_to_col.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_scale.c ++ $(MV) -f ../Source/umfpack_scale.o umfpack_oz_scale.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_load_numeric.c ++ $(MV) -f ../Source/umfpack_load_numeric.o umfpack_oz_load_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_save_numeric.c ++ $(MV) -f ../Source/umfpack_save_numeric.o umfpack_oz_save_numeric.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_load_symbolic.c ++ $(MV) -f ../Source/umfpack_load_symbolic.o umfpack_oz_load_symbolic.o ++ $(MKOCT) -DZINT -c ../Source/umfpack_save_symbolic.c ++ $(MV) -f ../Source/umfpack_save_symbolic.o umfpack_oz_save_symbolic.o ++ $(MKOCT) -c ../Source/umfpack_timer.c ++ $(MV) -f ../Source/umfpack_timer.o umfpack_m_timer.o ++ $(MKOCT) -c ../Source/umfpack_tictoc.c ++ $(MV) -f ../Source/umfpack_tictoc.o umfpack_m_tictoc.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_aat.c ++ $(MV) -f ../../AMD/Source/amd_aat.o amd_m_aat.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_1.c ++ $(MV) -f ../../AMD/Source/amd_1.o amd_m_1.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_2.c ++ $(MV) -f ../../AMD/Source/amd_2.o amd_m_2.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_dump.c ++ $(MV) -f ../../AMD/Source/amd_dump.o amd_m_dump.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_postorder.c ++ $(MV) -f ../../AMD/Source/amd_postorder.o amd_m_postorder.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_post_tree.c ++ $(MV) -f ../../AMD/Source/amd_post_tree.o amd_m_post_tree.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_defaults.c ++ $(MV) -f ../../AMD/Source/amd_defaults.o amd_m_defaults.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_order.c ++ $(MV) -f ../../AMD/Source/amd_order.o amd_m_order.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_control.c ++ $(MV) -f ../../AMD/Source/amd_control.o amd_m_control.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_info.c ++ $(MV) -f ../../AMD/Source/amd_info.o amd_m_info.o ++ $(MKOCT) -DDINT -c ../../AMD/Source/amd_valid.c ++ $(MV) -f ../../AMD/Source/amd_valid.o amd_m_valid.o ++ $(MKOCT) -o umfpack.oct $(OCT_SPARSE_INC) umfpack.cc \ ++ umf_o_analyze.o umf_o_apply_order.o umf_o_colamd.o umf_o_free.o \ ++ umf_o_fsize.o umf_o_is_permutation.o umf_o_malloc.o \ ++ umf_o_realloc.o umf_o_report_perm.o umf_o_singletons.o \ ++ umf_od_lhsolve.o umf_od_uhsolve.o umf_od_triplet_map_nox.o \ ++ umf_od_triplet_nomap_x.o umf_od_triplet_nomap_nox.o \ ++ umf_od_triplet_map_x.o umf_od_assemble_fixq.o \ ++ umf_od_store_lu_drop.o umf_od_assemble.o umf_od_blas3_update.o \ ++ umf_od_build_tuples.o umf_od_create_element.o umf_od_dump.o \ ++ umf_od_extend_front.o umf_od_garbage_collection.o \ ++ umf_od_get_memory.o umf_od_init_front.o umf_od_kernel.o \ ++ umf_od_kernel_init.o umf_od_kernel_wrapup.o umf_od_local_search.o \ ++ umf_od_lsolve.o umf_od_ltsolve.o umf_od_mem_alloc_element.o \ ++ umf_od_mem_alloc_head_block.o umf_od_mem_alloc_tail_block.o \ ++ umf_od_mem_free_tail_block.o umf_od_mem_init_memoryspace.o \ ++ umf_od_report_vector.o umf_od_row_search.o umf_od_scale_column.o \ ++ umf_od_set_stats.o umf_od_solve.o umf_od_symbolic_usage.o \ ++ umf_od_transpose.o umf_od_tuple_lengths.o umf_od_usolve.o \ ++ umf_od_utsolve.o umf_od_valid_numeric.o umf_od_valid_symbolic.o \ ++ umf_od_grow_front.o umf_od_start_front.o umf_od_2by2.o \ ++ umf_od_store_lu.o umf_od_scale.o umfpack_od_wsolve.o \ ++ umfpack_od_col_to_triplet.o umfpack_od_defaults.o \ ++ umfpack_od_free_numeric.o umfpack_od_free_symbolic.o \ ++ umfpack_od_get_numeric.o umfpack_od_get_lunz.o \ ++ umfpack_od_get_symbolic.o umfpack_od_numeric.o \ ++ umfpack_od_qsymbolic.o umfpack_od_report_control.o \ ++ umfpack_od_report_info.o umfpack_od_report_matrix.o \ ++ umfpack_od_report_numeric.o umfpack_od_report_perm.o \ ++ umfpack_od_report_status.o umfpack_od_report_symbolic.o \ ++ umfpack_od_report_triplet.o umfpack_od_report_vector.o \ ++ umfpack_od_solve.o umfpack_od_symbolic.o umfpack_od_transpose.o \ ++ umfpack_od_triplet_to_col.o umfpack_od_scale.o \ ++ umfpack_od_load_numeric.o umfpack_od_save_numeric.o \ ++ umfpack_od_load_symbolic.o umfpack_od_save_symbolic.o \ ++ umf_oz_lhsolve.o umf_oz_uhsolve.o umf_oz_triplet_map_nox.o \ ++ umf_oz_triplet_nomap_x.o umf_oz_triplet_nomap_nox.o \ ++ umf_oz_triplet_map_x.o umf_oz_assemble_fixq.o \ ++ umf_oz_store_lu_drop.o umf_oz_assemble.o umf_oz_blas3_update.o \ ++ umf_oz_build_tuples.o umf_oz_create_element.o umf_oz_dump.o \ ++ umf_oz_extend_front.o umf_oz_garbage_collection.o \ ++ umf_oz_get_memory.o umf_oz_init_front.o umf_oz_kernel.o \ ++ umf_oz_kernel_init.o umf_oz_kernel_wrapup.o umf_oz_local_search.o \ ++ umf_oz_lsolve.o umf_oz_ltsolve.o umf_oz_mem_alloc_element.o \ ++ umf_oz_mem_alloc_head_block.o umf_oz_mem_alloc_tail_block.o \ ++ umf_oz_mem_free_tail_block.o umf_oz_mem_init_memoryspace.o \ ++ umf_oz_report_vector.o umf_oz_row_search.o umf_oz_scale_column.o \ ++ umf_oz_set_stats.o umf_oz_solve.o umf_oz_symbolic_usage.o \ ++ umf_oz_transpose.o umf_oz_tuple_lengths.o umf_oz_usolve.o \ ++ umf_oz_utsolve.o umf_oz_valid_numeric.o umf_oz_valid_symbolic.o \ ++ umf_oz_grow_front.o umf_oz_start_front.o umf_oz_2by2.o \ ++ umf_oz_store_lu.o umf_oz_scale.o umfpack_oz_wsolve.o \ ++ umfpack_oz_col_to_triplet.o umfpack_oz_defaults.o \ ++ umfpack_oz_free_numeric.o umfpack_oz_free_symbolic.o \ ++ umfpack_oz_get_numeric.o umfpack_oz_get_lunz.o \ ++ umfpack_oz_get_symbolic.o umfpack_oz_numeric.o \ ++ umfpack_oz_qsymbolic.o umfpack_oz_report_control.o \ ++ umfpack_oz_report_info.o umfpack_oz_report_matrix.o \ ++ umfpack_oz_report_numeric.o umfpack_oz_report_perm.o \ ++ umfpack_oz_report_status.o umfpack_oz_report_symbolic.o \ ++ umfpack_oz_report_triplet.o umfpack_oz_report_vector.o \ ++ umfpack_oz_solve.o umfpack_oz_symbolic.o umfpack_oz_transpose.o \ ++ umfpack_oz_triplet_to_col.o umfpack_oz_scale.o \ ++ umfpack_oz_load_numeric.o umfpack_oz_save_numeric.o \ ++ umfpack_oz_load_symbolic.o umfpack_oz_save_symbolic.o \ ++ umfpack_o_timer.o umfpack_o_tictoc.o \ ++ amd_o_aat.o amd_o_1.o amd_o_2.o amd_o_dump.o \ ++ amd_o_postorder.o amd_o_post_tree.o amd_o_defaults.o amd_o_order.o \ ++ amd_o_control.o amd_o_info.o amd_o_valid.o ++ ++luflop: luflop.cc ++ $(MKOCT) luflop.cc -I$(OCT_SPARSE_INC) -o luflop.oct ++ ++#---------------------------------------- ++# umfpack library to link with octave ++#---------------------------------------- ++ ++octave: umfpack ++ ld -r -o ../../../$(OCTUMFPACK_LIB) \ ++ umf_o_analyze.o umf_o_apply_order.o umf_o_colamd.o umf_o_free.o \ ++ umf_o_fsize.o umf_o_is_permutation.o umf_o_malloc.o \ ++ umf_o_realloc.o umf_o_report_perm.o umf_o_singletons.o \ ++ umf_od_lhsolve.o umf_od_uhsolve.o umf_od_triplet_map_nox.o \ ++ umf_od_triplet_nomap_x.o umf_od_triplet_nomap_nox.o \ ++ umf_od_triplet_map_x.o umf_od_assemble_fixq.o \ ++ umf_od_store_lu_drop.o umf_od_assemble.o umf_od_blas3_update.o \ ++ umf_od_build_tuples.o umf_od_create_element.o umf_od_dump.o \ ++ umf_od_extend_front.o umf_od_garbage_collection.o \ ++ umf_od_get_memory.o umf_od_init_front.o umf_od_kernel.o \ ++ umf_od_kernel_init.o umf_od_kernel_wrapup.o umf_od_local_search.o \ ++ umf_od_lsolve.o umf_od_ltsolve.o umf_od_mem_alloc_element.o \ ++ umf_od_mem_alloc_head_block.o umf_od_mem_alloc_tail_block.o \ ++ umf_od_mem_free_tail_block.o umf_od_mem_init_memoryspace.o \ ++ umf_od_report_vector.o umf_od_row_search.o umf_od_scale_column.o \ ++ umf_od_set_stats.o umf_od_solve.o umf_od_symbolic_usage.o \ ++ umf_od_transpose.o umf_od_tuple_lengths.o umf_od_usolve.o \ ++ umf_od_utsolve.o umf_od_valid_numeric.o umf_od_valid_symbolic.o \ ++ umf_od_grow_front.o umf_od_start_front.o umf_od_2by2.o \ ++ umf_od_store_lu.o umf_od_scale.o umfpack_od_wsolve.o \ ++ umfpack_od_col_to_triplet.o umfpack_od_defaults.o \ ++ umfpack_od_free_numeric.o umfpack_od_free_symbolic.o \ ++ umfpack_od_get_numeric.o umfpack_od_get_lunz.o \ ++ umfpack_od_get_symbolic.o umfpack_od_numeric.o \ ++ umfpack_od_qsymbolic.o umfpack_od_report_control.o \ ++ umfpack_od_report_info.o umfpack_od_report_matrix.o \ ++ umfpack_od_report_numeric.o umfpack_od_report_perm.o \ ++ umfpack_od_report_status.o umfpack_od_report_symbolic.o \ ++ umfpack_od_report_triplet.o umfpack_od_report_vector.o \ ++ umfpack_od_solve.o umfpack_od_symbolic.o umfpack_od_transpose.o \ ++ umfpack_od_triplet_to_col.o umfpack_od_scale.o \ ++ umfpack_od_load_numeric.o umfpack_od_save_numeric.o \ ++ umfpack_od_load_symbolic.o umfpack_od_save_symbolic.o \ ++ umf_oz_lhsolve.o umf_oz_uhsolve.o umf_oz_triplet_map_nox.o \ ++ umf_oz_triplet_nomap_x.o umf_oz_triplet_nomap_nox.o \ ++ umf_oz_triplet_map_x.o umf_oz_assemble_fixq.o \ ++ umf_oz_store_lu_drop.o umf_oz_assemble.o umf_oz_blas3_update.o \ ++ umf_oz_build_tuples.o umf_oz_create_element.o umf_oz_dump.o \ ++ umf_oz_extend_front.o umf_oz_garbage_collection.o \ ++ umf_oz_get_memory.o umf_oz_init_front.o umf_oz_kernel.o \ ++ umf_oz_kernel_init.o umf_oz_kernel_wrapup.o umf_oz_local_search.o \ ++ umf_oz_lsolve.o umf_oz_ltsolve.o umf_oz_mem_alloc_element.o \ ++ umf_oz_mem_alloc_head_block.o umf_oz_mem_alloc_tail_block.o \ ++ umf_oz_mem_free_tail_block.o umf_oz_mem_init_memoryspace.o \ ++ umf_oz_report_vector.o umf_oz_row_search.o umf_oz_scale_column.o \ ++ umf_oz_set_stats.o umf_oz_solve.o umf_oz_symbolic_usage.o \ ++ umf_oz_transpose.o umf_oz_tuple_lengths.o umf_oz_usolve.o \ ++ umf_oz_utsolve.o umf_oz_valid_numeric.o umf_oz_valid_symbolic.o \ ++ umf_oz_grow_front.o umf_oz_start_front.o umf_oz_2by2.o \ ++ umf_oz_store_lu.o umf_oz_scale.o umfpack_oz_wsolve.o \ ++ umfpack_oz_col_to_triplet.o umfpack_oz_defaults.o \ ++ umfpack_oz_free_numeric.o umfpack_oz_free_symbolic.o \ ++ umfpack_oz_get_numeric.o umfpack_oz_get_lunz.o \ ++ umfpack_oz_get_symbolic.o umfpack_oz_numeric.o \ ++ umfpack_oz_qsymbolic.o umfpack_oz_report_control.o \ ++ umfpack_oz_report_info.o umfpack_oz_report_matrix.o \ ++ umfpack_oz_report_numeric.o umfpack_oz_report_perm.o \ ++ umfpack_oz_report_status.o umfpack_oz_report_symbolic.o \ ++ umfpack_oz_report_triplet.o umfpack_oz_report_vector.o \ ++ umfpack_oz_solve.o umfpack_oz_symbolic.o umfpack_oz_transpose.o \ ++ umfpack_oz_triplet_to_col.o umfpack_oz_scale.o \ ++ umfpack_oz_load_numeric.o umfpack_oz_save_numeric.o \ ++ umfpack_oz_load_symbolic.o umfpack_oz_save_symbolic.o \ ++ umfpack_o_timer.o umfpack_o_tictoc.o \ ++ amd_o_aat.o amd_o_1.o amd_o_2.o amd_o_dump.o \ ++ amd_o_postorder.o amd_o_post_tree.o amd_o_defaults.o amd_o_order.o \ ++ amd_o_control.o amd_o_info.o amd_o_valid.o ++ ++#------------------------------------------------------------------------------- ++# Remove all but the files in the original distribution ++#------------------------------------------------------------------------------- ++ ++purge: clean ++ - $(RM) *.oct* *.dll +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_btf.m UMFPACK/UMFPACK/OCTAVE/umfpack_btf.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_btf.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_btf.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,129 @@ ++function x = umfpack_btf (A, b, Control) ++% UMFPACK_BTF ++% ++% x = umfpack_btf (A, b, Control) ++% ++% solve Ax=b by first permuting the matrix A to block triangular form via dmperm ++% and then using UMFPACK to factorize each diagonal block. Adjacent 1-by-1 ++% blocks are merged into a single upper triangular block, and solved via ++% MATLAB's \ operator. The Control parameter is optional (Type umfpack_details ++% and umfpack_report for details on its use). A must be square. ++% ++% See also: umfpack, umfpack_factorize, umfpack_details, dmperm ++ ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. Type umfpack_details for License. ++ ++if (nargin < 2) ++ help umfpack_btf ++ error ('Usage: x = umfpack_btf (A, b, Control)') ; ++end ++ ++[m n] = size (A) ; ++if (m ~= n) ++ help umfpack_btf ++ error ('umfpack_btf: A must be square') ; ++end ++[m1 n1] = size (b) ; ++if (m1 ~= n) ++ help umfpack_btf ++ error ('umfpack_btf: b has the wrong dimensions') ; ++end ++ ++if (nargin < 3) ++ Control = umfpack ; ++end ++ ++%------------------------------------------------------------------------------- ++% find the block triangular form ++%------------------------------------------------------------------------------- ++ ++[p,q,r] = dmperm (A) ; ++nblocks = length (r) - 1 ; ++ ++%------------------------------------------------------------------------------- ++% solve the system ++%------------------------------------------------------------------------------- ++ ++if (nblocks == 1 | sprank (A) < n) ++ ++ %--------------------------------------------------------------------------- ++ % matrix is irreducible or structurally singular ++ %--------------------------------------------------------------------------- ++ ++ x = umfpack_solve (A, '\\', b, Control) ; ++ ++else ++ ++ %--------------------------------------------------------------------------- ++ % A (p,q) is in block triangular form ++ %--------------------------------------------------------------------------- ++ ++ b = b (p,:) ; ++ A = A (p,q) ; ++ x = zeros (size (b)) ; ++ ++ %--------------------------------------------------------------------------- ++ % merge adjacent singletons into a single upper triangular block ++ %--------------------------------------------------------------------------- ++ ++ [r, nblocks, is_triangular] = merge_singletons (r) ; ++ ++ %--------------------------------------------------------------------------- ++ % solve the system: x (q) = A\b ++ %--------------------------------------------------------------------------- ++ ++ for k = nblocks:-1:1 ++ ++ % get the kth block ++ k1 = r (k) ; ++ k2 = r (k+1) - 1 ; ++ ++ % solve the system ++ x (k1:k2,:) = solver (A (k1:k2, k1:k2), b (k1:k2,:), ... ++ is_triangular (k), Control) ; ++ ++ % off-diagonal block back substitution ++ b (1:k1-1,:) = b (1:k1-1,:) - A (1:k1-1, k1:k2) * x (k1:k2,:) ; ++ ++ end ++ ++ x (q,:) = x ; ++ ++end ++ ++%------------------------------------------------------------------------------- ++% merge_singletons ++%------------------------------------------------------------------------------- ++ ++function [r, nblocks, is_triangular] = merge_singletons (r) ++% ++% Given r from [p,q,r] = dmperm (A), where A is square, return a modified r that ++% reflects the merger of adjacent singletons into a single upper triangular ++% block. is_triangular (k) is 1 if the kth block is upper triangular. nblocks ++% is the number of new blocks. ++ ++nblocks = length (r) - 1 ; ++bsize = r (2:nblocks+1) - r (1:nblocks) ; ++t = [0 (bsize == 1)] ; ++z = (t (1:nblocks) == 0 & t (2:nblocks+1) == 1) | t (2:nblocks+1) == 0 ; ++y = [(find (z)) nblocks+1] ; ++r = r (y) ; ++nblocks = length (y) - 1 ; ++is_triangular = y (2:nblocks+1) - y (1:nblocks) > 1 ; ++ ++%------------------------------------------------------------------------------- ++% solve Ax=b, but check for small and/or triangular systems ++%------------------------------------------------------------------------------- ++ ++function x = solver (A, b, is_triangular, Control) ++if (is_triangular) ++ % back substitution only ++ x = A \ b ; ++elseif (size (A,1) < 4) ++ % a very small matrix, solve it as a dense linear system ++ x = full (A) \ b ; ++else ++ % solve it as a sparse linear system ++ x = umfpack_solve (A, '\\', b, Control) ; ++end +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack.cc UMFPACK/UMFPACK/OCTAVE/umfpack.cc +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack.cc 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack.cc 2005-02-01 21:58:15.885225363 +0100 +@@ -0,0 +1,1399 @@ ++/* ++ ++Copyright (C) 2004 David Bateman ++ ++This program is free software; you can redistribute it and/or modify it ++under the terms of the GNU General Public License as published by the ++Free Software Foundation; either version 2, or (at your option) any ++later version. ++ ++This program is distributed in the hope that it will be useful, but WITHOUT ++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; see the file COPYING. If not, write to the Free ++Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++In addition to the terms of the GPL, you are permitted to link ++this program with any Open Source program, as defined by the ++Open Source Initiative (www.opensource.org) ++ ++*/ ++ ++/* ++ ++This is the Octave interface to the UMFPACK code, which bore the following ++copyright ++ ++ UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++ Davis. All Rights Reserved. See ../README for License. ++ email: davis@cise.ufl.edu CISE Department, Univ. of Florida. ++ web: http://www.cise.ufl.edu/research/sparse/umfpack ++ ++*/ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ov-re-sparse.h" ++#include "ov-cx-sparse.h" ++ ++// External UMFPACK functions in C ++extern "C" { ++#include "umfpack.h" ++} ++ ++#define MIN(a,b) (((a) < (b)) ? (a) : (b)) ++#define MAX(a,b) (((a) > (b)) ? (a) : (b)) ++ ++// Return an error message ++static ++void umfpack_error (const char *s, int A_is_complex, int nargout, ++ octave_value_list retval, NDArray Control, ++ NDArray Info, int status, int do_info) ++{ ++ if (A_is_complex) ++ { ++ umfpack_zi_report_status (Control.fortran_vec (), status) ; ++ umfpack_zi_report_info (Control.fortran_vec (), Info.fortran_vec ()) ; ++ } ++ else ++ { ++ umfpack_di_report_status (Control.fortran_vec (), status) ; ++ umfpack_di_report_info (Control.fortran_vec (), Info.fortran_vec ()) ; ++ } ++ if (do_info > 0) ++ // return Info ++ retval (do_info) = octave_value (Info); ++ ++ error (s); ++} ++ ++DEFUN_DLD (umfpack, args, nargout, ++ "-*- texinfo -*-\n\ ++@deftypefn {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, '\\', @var{b})\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, '\\', @var{b}, @var{Control})\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, '\\', @var{b}, @var{Control})\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, '\\', b)\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', A) ;\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Qinit}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Qinit}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Qinit}) ;\n\ ++@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Qinit}, @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, 'symbolic') ;\n\ ++@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, 'symbolic', @var{Control}) ;\n\ ++@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, @var{Qinit}, 'symbolic') ;\n\ ++@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, @var{Qinit}, 'symbolic', @var{Control});\n\ ++@deftypefnx {Loadable Function} {@var{Control} =} umfpack ;\n\ ++\n\ ++UMFPACK v4.3 is a Octave oct-file for solving sparse linear systems.\n\ ++\n\ ++@iftex\n\ ++@tex\n\ ++\\vskip 2ex\n\ ++\\hfil\\vbox{\n\ ++\\offinterlineskip\n\ ++\\tabskip=0pt\n\ ++\\halign{\n\ ++\\vrule height1.75ex depth1.25ex width 0.6pt #\\tabskip=1em &\n\ ++\\hfil #\\hfil &\\vrule # & \n\ ++\\hfil #\\hfil &\\vrule # width 0.6pt \\tabskip=0pt\\cr\n\ ++\\noalign{\\hrule height 0.6pt}\n\ ++& UMFPACK v4.3 && OCTAVE approximate equivalent &\\cr\n\ ++\\noalign{\\hrule} \n\ ++& x = umfpack (A, '\\', b) ; && x = A \\ b &\\cr\n\ ++& && &\\cr\n\ ++&x = umfpack (b, '/', A) ; && x = b / A &\\cr\n\ ++& && &\\cr\n\ ++&[L,U,P,Q] = umfpack (A) ; && [m,n] = size (A) ; &\\cr\n\ ++& && I = speye (n) ; &\\cr\n\ ++& && Q = I (:, colamd (A)) ; &\\cr\n\ ++& && [L,U,P] = lu (A*Q) ; &\\cr\n\ ++& && &\\cr\n\ ++&[L,U,P,Q,R] = umfpack (A) ; && [m,n] = size (A) ; &\\cr\n\ ++& && I = speye (n) ; &\\cr\n\ ++& && Q = I (:, colamd (A)) ; &\\cr\n\ ++& && r = full (sum (abs (A), 2)) ; &\\cr\n\ ++& && r (find (r == 0)) = 1 ; &\\cr\n\ ++& && R = spdiags (r, 0, m, m) ; &\\cr\n\ ++& && [L,U,P] = lu ((R\\A)*Q) ; &\\cr\n\ ++& && &\\cr\n\ ++&[P,Q,F,C] = umfpack (A, 'symbolic')&& [m,n] = size (A) ; &\\cr\n\ ++& && I = speye (n) ; &\\cr\n\ ++& && Q = I (:, colamd (A)) ; &\\cr\n\ ++& && [count,h,parent,post] = ... &\\cr\n\ ++& && symbfact (A*Q, 'col') ; &\\cr\n\ ++\\noalign{\\hrule height 0.6pt}\n\ ++}}\\hfil\n\ ++\\vskip 1ex\n\ ++@end tex\n\ ++@end iftex\n\ ++@ifinfo\n\ ++@multitable @columnfractions 0.43 .02 .43\n\ ++@item UMFPACK v4.3: @tab | \n\ ++@tab OCTAVE approx. equivalent\n\ ++@item ------------------------------- @tab | \n\ ++@tab --------------------------------\n\ ++@item x = umfpack (A, '\\', b) ; @tab | \n\ ++@tab x = A \\ b\n\ ++@item @tab | \n\ ++@tab\n\ ++@item x = umfpack (b, '/', A) ; @tab | \n\ ++@tab x = b / A\n\ ++@item @tab | \n\ ++@tab\n\ ++@item [L,U,P,Q] = umfpack (A) ; @tab | \n\ ++@tab [m,n] = size (A) ;\n\ ++@item @tab | \n\ ++@tab I = speye (n) ;\n\ ++@item @tab | \n\ ++@tab Q = I (:, colamd (A)) ;\n\ ++@item @tab | \n\ ++@tab [L,U,P] = lu (A*Q) ;\n\ ++@item @tab | \n\ ++@tab\n\ ++@item [L,U,P,Q,R] = umfpack (A) ; @tab | \n\ ++@tab [m,n] = size (A) ;\n\ ++@item @tab | \n\ ++@tab I = speye (n) ;\n\ ++@item @tab | \n\ ++@tab Q = I (:, colamd (A)) ;\n\ ++@item @tab | \n\ ++@tab r = full (sum (abs (A), 2)) ;\n\ ++@item @tab | \n\ ++@tab r (find (r == 0)) = 1 ;\n\ ++@item @tab | \n\ ++@tab R = spdiags (r, 0, m, m) ;\n\ ++@item @tab | \n\ ++@tab [L,U,P] = lu ((R\\A)*Q) ;\n\ ++@item @tab | \n\ ++@tab\n\ ++@item [P,Q,F,C] = umfpack (A, 'symbolic') @tab | \n\ ++@tab [m,n] = size (A) ; \n\ ++@item @tab | \n\ ++@tab I = speye (n) ;\n\ ++@item @tab | \n\ ++@tab Q = I (:, colamd (A)) ;\n\ ++@item @tab | \n\ ++@tab [count,h,parent,post] = ...\n\ ++@item @tab | \n\ ++@tab symbfact (A*Q, 'col') ;\n\ ++@end multitable\n\ ++@end ifinfo\n\ ++\n\ ++A must be sparse. It can be complex, singular, and/or rectangular.\n\ ++A must be square for '/' or '\\'. b must be a full real or complex\n\ ++vector. For @code{[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}] =\n\ ++umfpack (@var{a})}, the factorization is @code{@var{l} * @var{u} =\n\ ++@var{p} * (@var{r} \\ @var{a}) * @var{q}}. If @var{a} has a mostly\n\ ++symmetric nonzero pattern, then replace @dfn{colamd} with @dfn{amd}\n\ ++in the OCTAVE-equivalent column in the table above.\n\ ++\n\ ++Factor or solve a sparse linear system, returning either the solution\n\ ++@var{x} to @code{@var{A} * @var{x} = @var{b}} or @code{@var{A}' * @var{x}'\n\ ++= @var{b}'}, the factorization LU=PAQ, or LU=P(R\\A)Q. A must be sparse.\n\ ++For the solve, A must be square and b must be a dense n-by-1 vector. For LU\n\ ++factorization, A can be rectangular. In both cases, A and/or b can be real\n\ ++or complex.\n\ ++\n\ ++UMFPACK analyzes the matrix and selects one of three strategies to factorize\n\ ++the matrix. It first finds a set of k initial pivot entries of zero\n\ ++Markowitz cost. This forms the first k rows and columns of L and U. The\n\ ++remaining submatrix S is then analyzed, based on the symmetry of the nonzero\n\ ++pattern of the submatrix and the values on the diagaonal. The strategies\n\ ++include:\n\ ++\n\ ++@table @asis\n\ ++@item unsymmetric\n\ ++Use a COLAMD pre-ordering, a column elimination tree\n\ ++post-ordering, refine the column ordering during factorization,\n\ ++and make no effort at selecting pivots on the diagonal.\n\ ++@item 2-by-2\n\ ++Like the symmetric strategy (see below), except that local\n\ ++row permutations are first made to attempt to place large entries\n\ ++on the diagonal.\n\ ++@item symmetric\n\ ++Use an AMD pre-ordering on the matrix @code{@var{s} + @var{s}'}, an\n\ ++elimination tree post-ordering, do not refine the column ordering during\n\ ++factorization, and attempt to select pivots on the diagonal.\n\ ++@end table\n\ ++\n\ ++Each of the following uses of umfpack (except for 'Control = umfpack') is\n\ ++stand-alone. That is, no call to umfpack is required for any subsequent\n\ ++call. In each usage, the Info output argument is optional.\n\ ++\n\ ++Usage:\n\ ++\n\ ++[x, Info] = umfpack (A, '\\', b) ;\n\ ++[x, Info] = umfpack (A, '\\', b, Control) ;\n\ ++[x, Info] = umfpack (A, Qinit, '\\', b, Control) ;\n\ ++[x, Info] = umfpack (A, Qinit, '\\', b) ;\n\ ++\n\ ++ Solves Ax=b (similar to x = A\\b in OCTAVE).\n\ ++\n\ ++[x, Info] = umfpack (b, '/', A) ;\n\ ++[x, Info] = umfpack (b, '/', A, Control) ;\n\ ++[x, Info] = umfpack (b, '/', A, Qinit) ;\n\ ++[x, Info] = umfpack (b, '/', A, Qinit, Control) ;\n\ ++\n\ ++ Solves A'x'=b' (similar to x = b/A in OCTAVE).\n\ ++\n\ ++[L, U, P, Q, R, Info] = umfpack (A) ;\n\ ++[L, U, P, Q, R, Info] = umfpack (A, Control) ;\n\ ++[L, U, P, Q, R, Info] = umfpack (A, Qinit) ;\n\ ++[L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ;\n\ ++\n\ ++ Returns the LU factorization of A. P and Q are returned as permutation\n\ ++ matrices. R is a diagonal sparse matrix of scale factors for the rows\n\ ++ of A, L is lower triangular, and U is upper triangular. The\n\ ++ factorization is L*U = P*(R\\A)*Q. You can turn off scaling by setting\n\ ++ Control (17) to zero (in which case R = speye (m)), or by using the\n\ ++ following syntaxes (in which case Control (17) is ignored):\n\ ++\n\ ++[L, U, P, Q] = umfpack (A) ;\n\ ++[L, U, P, Q] = umfpack (A, Control) ;\n\ ++[L, U, P, Q] = umfpack (A, Qinit) ;\n\ ++[L, U, P, Q] = umfpack (A, Qinit, Control) ;\n\ ++\n\ ++ Same as above, except that no row scaling is performed. The Info array\n\ ++ is not returned, either.\n\ ++\n\ ++[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ;\n\ ++[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic', Control) ;\n\ ++[P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic') ;\n\ ++[P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic', Control);\n\ ++\n\ ++ Performs only the fill-reducing column pre-ordering (including the\n\ ++ elimination tree post-ordering) and symbolic factorization. Q1 is the\n\ ++ initial column permutation (either from colamd, amd, or the input\n\ ++ ordering Qinit), possibly followed by a column elimination tree post-\n\ ++ ordering or a symmetric elimination tree post-ordering, depending on\n\ ++ the strategy used.\n\ ++\n\ ++ For the unsymmetric strategy, P1 is the row ordering induced by Q1\n\ ++ (row-merge order). For the 2-by-2 strategy, P1 is the row ordering that\n\ ++ places large entries on the diagonal of P1*A*Q1. For the symmetric\n\ ++ strategy, P1 = Q1.\n\ ++\n\ ++ Fr is a (nfr+1)-by-4 array containing information about each frontal\n\ ++ matrix, where nfr <= n is the number of frontal matrices. Fr (:,1) is\n\ ++ the number of pivot columns in each front, and Fr (:,2) is the parent\n\ ++ of each front in the supercolumn elimination tree. Fr (k,2) is zero if\n\ ++ k is a root. The first Fr (1,1) columns of P1*A*Q1 are the pivot\n\ ++ columns for the first front, the next Fr (2,1) columns of P1*A*Q1\n\ ++ are the pivot columns for the second front, and so on.\n\ ++\n\ ++ For the unsymmetric strategy, Fr (:,3) is the row index of the first\n\ ++ row in P1*A*Q1 whose leftmost nonzero entry is in a pivot column for\n\ ++ the kth front. Fr (:,4) is the leftmost descendent of the kth front.\n\ ++ Rows in the range Fr (Fr (k,4),3) to Fr (k+1,3)-1 form the entire set\n\ ++ of candidate pivot rows for the kth front (some of these will typically\n\ ++ have been selected as pivot rows of fronts Fr (k,3) to k-1, before the\n\ ++ factorization reaches the kth front. If front k is a leaf node, then\n\ ++ Fr (k,4) is k.\n\ ++\n\ ++ Ch is a (nchains+1)-by-3 array containing information about each\n\ ++ 'chain' (unifrontal sequence) of frontal matrices, and where\n\ ++ nchains <= nfr is the number of chains. The ith chain consists of\n\ ++ frontal matrices. Chain (i,1) to Chain (i+1,1)-1, and the largest\n\ ++ front in chain i is Chain (i,2)-by-Chain (i,3).\n\ ++\n\ ++ This use of umfpack is not required to factor or solve a linear system\n\ ++ in OCTAVE. It analyzes the matrix A and provides information only.\n\ ++ The OCTAVE statement @code{treeplot (Fr (:,2)')} plots the column\n\ ++ elimination tree.\n\ ++\n\ ++Control = umfpack ;\n\ ++\n\ ++ Returns a 20-by-1 vector of default parameter settings for umfpack.\n\ ++\n\ ++umfpack_report (Control, Info) ;\n\ ++\n\ ++ Prints the current Control settings, and Info\n\ ++\n\ ++If present, Qinit is a user-supplied 1-by-n permutation vector. It is an\n\ ++initial fill-reducing column pre-ordering for A; if not present, then colamd\n\ ++or amd are used instead. If present, Control is a user-supplied 20-by-1\n\ ++array. Control and Info are optional; if Control is not present, defaults\n\ ++are used. If a Control entry is NaN, then the default is used for that entry.\n\ ++\n\ ++UMFPACK Version 4.3 (Jan. 16, 2004), Copyright @copyright{} 2004 by\n\ ++Timothy A. Davis. All Rights Reserved.\n\ ++\n\ ++UMFPACK License:\n\ ++\n\ ++@example\n\ ++Your use or distribution of UMFPACK or any modified version of\n\ ++UMFPACK implies that you agree to this License.\n\ ++\n\ ++THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY\n\ ++EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.\n\ ++\n\ ++Permission is hereby granted to use or copy this program, provided\n\ ++that the Copyright, this License, and the Availability of the original\n\ ++version is retained on all copies. User documentation of any code that\n\ ++uses UMFPACK or any modified version of UMFPACK code must cite the\n\ ++Copyright, this License, the Availability note, and 'Used by permission.'\n\ ++Permission to modify the code and to distribute modified code is granted,\n\ ++provided the Copyright, this License, and the Availability note are\n\ ++retained, and a notice that the code was modified is included. This\n\ ++software was developed with support from the National Science Foundation,\n\ ++and is provided to you free of charge.\n\ ++@end example\n\ ++\n\ ++Availability: http://www.cise.ufl.edu/research/sparse/umfpack\n\ ++@end deftypefn\n\ ++@seealso{lu_normtest, colamd, amd, umfpack_solve}") ++{ ++ octave_value_list retval; ++ int nargin = args.length (); ++ int op = 0; ++ std::string operation; ++ bool do_solve = false; ++ int do_info = 0; ++ ++ ColumnVector User_Qinit; ++ SparseComplexMatrix CAmatrix; ++ ComplexMatrix CBmatrix; ++ SparseMatrix Amatrix; ++ Matrix Bmatrix; ++ NDArray User_Control_matrix; ++ ++ bool A_is_complex = false; ++ bool B_is_complex = false; ++ bool X_is_complex = false; ++ bool transpose = false; ++ bool have_User_Qinit = false; ++ bool have_User_Control_matrix = false; ++ bool do_numeric = true; ++ bool no_scale = false; ++ ++ // find the operator ++ for (int i = 0 ; i < nargin ; i++) ++ { ++ if (args(i).is_string ()) ++ { ++ op = i; ++ break; ++ } ++ } ++ ++ if (op > 0) ++ { ++ std::string op_type = args (op).string_value (); ++ ++ if (op_type == "\\") ++ { ++ ++ // matrix left divide, x = A\b ++ ++ // [x, Info] = umfpack (A, '\', b) ; ++ // [x, Info] = umfpack (A, '\', b, Control) ; ++ // [x, Info] = umfpack (A, Qinit, '\', b, Control) ; ++ // [x, Info] = umfpack (A, Qinit, '\', b) ; ++ ++ do_solve = true; ++ operation = "x = A\\b"; ++ ++ if (args(0).class_name () != "sparse") ++ { ++ error ("umfpack: input matrix A must be sparse"); ++ return retval; ++ } ++ ++ if (args(0).is_complex_type ()) ++ { ++ CAmatrix = args(0).sparse_complex_matrix_value (); ++ A_is_complex = true; ++ } ++ else ++ Amatrix = args(0).sparse_matrix_value (); ++ ++ ++ if (args(op+1).is_complex_type ()) ++ { ++ CBmatrix = args(op+1).complex_matrix_value (); ++ B_is_complex = true; ++ } ++ else ++ Bmatrix = args(op+1).matrix_value (); ++ ++ if (nargout == 2) ++ do_info = 1; ++ ++ if (op == 2) ++ { ++ User_Qinit = args(1).column_vector_value (); ++ have_User_Qinit = true; ++ } ++ ++ if ((op == 1 && nargin == 4) || (op == 2 && nargin == 5)) ++ { ++ User_Control_matrix = args(nargin-1).array_value (); ++ have_User_Control_matrix = true; ++ } ++ ++ if (error_state) ++ { ++ error ("umfpack: incorrect argument type"); ++ return retval; ++ } ++ ++ if (nargin < 3 || nargin > 5 || nargout > 2) ++ { ++ error ("umfpack: wrong number of arguments"); ++ return retval; ++ } ++ ++ } ++ else if (op_type == "/") ++ { ++ // matrix right divide, x = b/A ++ ++ // [x, Info] = umfpack (b, '/', A) ; ++ // [x, Info] = umfpack (b, '/', A, Control) ; ++ // [x, Info] = umfpack (b, '/', A, Qinit) ; ++ // [x, Info] = umfpack (b, '/', A, Qinit, Control) ; ++ ++ do_solve = true; ++ operation = "x = b/A" ; ++ ++ transpose = true; ++ ++ if (args(2).class_name () != "sparse") ++ { ++ error ("umfpack: input matrix A must be sparse"); ++ return retval; ++ } ++ ++ if (args(2).is_complex_type ()) ++ { ++ CAmatrix = args(2).sparse_complex_matrix_value (); ++ A_is_complex = true; ++ } ++ else ++ Amatrix = args(2).sparse_matrix_value (); ++ ++ if (args(0).is_complex_type ()) ++ { ++ CBmatrix = args(0).complex_matrix_value (); ++ B_is_complex = true; ++ } ++ else ++ Bmatrix = args(0).matrix_value (); ++ ++ if (nargout == 2) ++ do_info = 1; ++ ++ if (nargin == 5) ++ { ++ User_Qinit = args(3).column_vector_value (); ++ User_Control_matrix = args(4).array_value (); ++ have_User_Qinit = true; ++ have_User_Control_matrix = true; ++ } ++ else if (nargin == 4) ++ { ++ User_Control_matrix = args(3).array_value (); ++ ++ if (User_Control_matrix.rows () == 1) ++ { ++ User_Qinit = args(3).column_vector_value (); ++ have_User_Qinit = true; ++ } ++ else ++ have_User_Control_matrix = true; ++ } ++ else if (nargin < 3 || nargin > 5 || nargout > 2) ++ { ++ error ("umfpack: wrong number of arguments"); ++ return retval; ++ } ++ ++ if (error_state) ++ { ++ error ("umfpack: incorrect argument type"); ++ return retval; ++ } ++ } ++ else if (op_type == "symbolic") ++ { ++ // symbolic factorization only ++ ++ // [P Q Fr Ch Info] = umfpack (A, 'symbolic') ; ++ // [P Q Fr Ch Info] = umfpack (A, 'symbolic', Control) ; ++ // [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic') ; ++ // [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic', Control) ; ++ ++ operation = "symbolic factorization"; ++ do_numeric = false; ++ ++ if (args(0).class_name () != "sparse") ++ { ++ error ("umfpack: input matrix A must be sparse"); ++ return retval; ++ } ++ ++ if (args(0).is_complex_type ()) ++ { ++ CAmatrix = args(0).sparse_complex_matrix_value (); ++ A_is_complex = true; ++ } ++ else ++ Amatrix = args(0).sparse_matrix_value (); ++ ++ if (nargout == 5) ++ do_info = 4 ; ++ ++ if (op == 2) ++ { ++ User_Qinit = args(1).column_vector_value (); ++ have_User_Qinit = true; ++ } ++ if ((op == 1 && nargin == 3) || (op == 2 && nargin == 4)) ++ { ++ User_Control_matrix = args(nargin-1).array_value (); ++ have_User_Control_matrix = true; ++ } ++ ++ if (error_state) ++ { ++ error ("umfpack: incorrect argument type"); ++ return retval; ++ } ++ ++ if (nargin < 2 || nargin > 4 || nargout > 5 || nargout < 4) ++ { ++ error ("umfpack: wrong number of arguments") ; ++ return retval; ++ } ++ } ++ else ++ { ++ error ("operator must be '/', '\\', or 'symbolic'") ; ++ return retval; ++ } ++ } ++ else if (nargin > 0) ++ { ++ // LU factorization ++ ++ // with scaling: ++ // [L, U, P, Q, R, Info] = umfpack (A) ; ++ // [L, U, P, Q, R, Info] = umfpack (A, Qinit) ; ++ // ++ // scaling determined by Control settings: ++ // [L, U, P, Q, R, Info] = umfpack (A, Control) ; ++ // [L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ; ++ // ++ // with no scaling: ++ // [L, U, P, Q] = umfpack (A) ; ++ // [L, U, P, Q] = umfpack (A, Control) ; ++ // [L, U, P, Q] = umfpack (A, Qinit) ; ++ // [L, U, P, Q] = umfpack (A, Qinit, Control) ; ++ ++ operation = "numeric factorization" ; ++ ++ if (args(0).is_complex_type ()) ++ { ++ CAmatrix = args(0).sparse_complex_matrix_value (); ++ A_is_complex = true; ++ } ++ else ++ Amatrix = args(0).sparse_matrix_value (); ++ ++ no_scale = nargout <= 4 ; ++ ++ if (nargout == 6) ++ do_info = 5 ; ++ ++ if (nargin == 3) ++ { ++ User_Qinit = args(1).column_vector_value (); ++ User_Control_matrix = args(2).array_value (); ++ have_User_Qinit = true; ++ have_User_Control_matrix = true; ++ } ++ else if (nargin == 2) ++ { ++ User_Control_matrix = args(1).array_value (); ++ ++ if (User_Control_matrix.rows () == 1) ++ { ++ User_Qinit = args(1).column_vector_value (); ++ have_User_Qinit = true; ++ } ++ else ++ have_User_Control_matrix = true; ++ } ++ else if (nargin > 3 || nargout > 6 || nargout < 4) ++ { ++ error ("umfpack: wrong number of arguments") ; ++ return retval; ++ } ++ } ++ else ++ { ++ // return default control settings ++ ++ // Control = umfpack ; ++ // umfpack ; ++ ++ if (nargout > 1) ++ { ++ error ("umfpack: wrong number of arguments") ; ++ return retval; ++ } ++ ++ NDArray user_control (dim_vector (UMFPACK_CONTROL, 1)); ++ double *user_control_ptr = user_control.fortran_vec (); ++ umfpack_di_defaults (user_control_ptr); ++ retval(0) = user_control; ++ return retval; ++ } ++ ++ // check inputs ++ ++ int n_row = Amatrix.rows (); ++ int n_col = Amatrix.cols (); ++ int nn = MAX (n_row, n_col) ; ++ int n_inner = MIN (n_row, n_col) ; ++ if (do_solve && n_row != n_col) ++ { ++ error ("umfpack: input matrix A must square for '\\' or '/'") ; ++ return retval; ++ } ++ if (n_row == 0 || n_col == 0) ++ { ++ error ("umfpack: input matrix A cannot have zero rows or zero columns") ; ++ return retval; ++ } ++ ++ /* The real/complex status of A determines which version to use, */ ++ /* (umfpack_di_* or umfpack_zi_*). */ ++ const int *Ap; ++ const int *Ai; ++ const double *Ax; ++ const double *Bx; ++ ++ if (A_is_complex) ++ { ++ Ap = CAmatrix.cidx (); ++ Ai = CAmatrix.ridx (); ++ Ax = X_CAST (const double *, CAmatrix.data ()); ++ } ++ else ++ { ++ Ap = Amatrix.cidx (); ++ Ai = Amatrix.ridx (); ++ Ax = Amatrix.data (); ++ } ++ ++ if (B_is_complex) ++ Bx = X_CAST (const double *, CBmatrix.fortran_vec ()); ++ else ++ Bx = Bmatrix.fortran_vec (); ++ ++ if (do_solve) ++ { ++ int b_row = Bmatrix.rows (); ++ int b_col = Bmatrix.cols (); ++ ++ if (!((transpose && b_row == 1 && b_col == nn) || ++ (!transpose && b_row == nn && b_col == 1))) ++ { ++ error ("umfpack: b has the wrong dimensions") ; ++ return retval; ++ } ++ ++ X_is_complex = A_is_complex || B_is_complex ; ++ } ++ ++ // set the Control parameters ++ NDArray Control (dim_vector (UMFPACK_CONTROL, 1)); ++ double *Control_ptr = Control.fortran_vec (); ++ if (A_is_complex) ++ umfpack_zi_defaults (Control_ptr) ; ++ else ++ umfpack_di_defaults (Control_ptr) ; ++ ++ if (have_User_Control_matrix) ++ { ++ int size = MIN (UMFPACK_CONTROL, User_Control_matrix.length ()); ++ for (int i = 0 ; i < size ; i++) ++ Control (i) = User_Control_matrix (i) ; ++ } ++ ++ if (no_scale) ++ { ++ // turn off scaling for [L, U, P, Q] = umfpack (A) ; ++ // ignoring the input value of Control (24) for the usage ++ // [L, U, P, Q] = umfpack (A, Control) ; ++ Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE ; ++ } ++ ++ int print_level; ++ if (xisnan (Control (UMFPACK_PRL))) ++ print_level = UMFPACK_DEFAULT_PRL ; ++ else ++ print_level = int (Control (UMFPACK_PRL)) ; ++ ++ Control (UMFPACK_PRL) = print_level ; ++ ++ // check Qinit, if present ++ int *Qinit = NULL; ++ if (have_User_Qinit) ++ { ++ if(User_Qinit.rows () != 1 || User_Qinit.cols () != n_col) ++ { ++ error ("umfpack: Qinit must be 1-by-n_col") ; ++ return retval; ++ } ++ ++ Qinit = new int [n_col]; ++ for (int i = 0; i < n_col; i++) ++ Qinit[i] = static_cast (User_Qinit (i)); ++ } ++ ++ // report the inputs A and Qinit ++ ++ if (print_level >= 2) ++ // print the operation ++ octave_stdout << "\numfpack: " << operation; ++ ++ if (A_is_complex) ++ { ++ umfpack_zi_report_control (Control_ptr) ; ++ ++ if (print_level >= 3) ++ octave_stdout << "\nA: " ; ++ ++ umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, NULL, ++ 1, Control_ptr) ; ++ if (have_User_Qinit) ++ { ++ if (print_level >= 3) ++ octave_stdout << "\nQinit: " ; ++ ++ umfpack_zi_report_perm (n_col, Qinit, Control_ptr) ; ++ } ++ } ++ else ++ { ++ umfpack_di_report_control (Control_ptr) ; ++ ++ if (print_level >= 3) ++ octave_stdout << "\nA: " ; ++ ++ umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, ++ 1, Control_ptr) ; ++ if (have_User_Qinit) ++ { ++ if (print_level >= 3) ++ octave_stdout << "\nQinit: " ; ++ ++ umfpack_di_report_perm (n_col, Qinit, Control_ptr) ; ++ } ++ } ++ ++#ifndef NO_TRANSPOSE_FORWARD_SLASH ++ // create the array transpose for x = b/A ++ if (transpose) ++ if (A_is_complex) ++ { ++ CAmatrix = CAmatrix.transpose (); ++ Ap = Amatrix.cidx (); ++ Ai = Amatrix.ridx (); ++ Ax = X_CAST (const double *, CAmatrix.data ()); ++ } ++ else ++ { ++ Amatrix = Amatrix.transpose (); ++ Ap = Amatrix.cidx (); ++ Ai = Amatrix.ridx (); ++ Ax = Amatrix.data (); ++ } ++#endif ++ ++ // perform the symbolic factorization ++ ++ NDArray InfoOut (dim_vector (1, UMFPACK_INFO)); ++ double * Info = InfoOut.fortran_vec (); ++ void *Symbolic; ++ int status, status2; ++ if (A_is_complex) ++ status = umfpack_zi_qsymbolic (n_row, n_col, Ap, Ai, Ax, NULL, ++ Qinit, &Symbolic, Control_ptr, ++ Info); ++ else ++ status = umfpack_di_qsymbolic (n_row, n_col, Ap, Ai, Ax, ++ Qinit, &Symbolic, Control_ptr, ++ Info); ++ ++ if (status < 0) ++ { ++ umfpack_error ("symbolic factorization failed", A_is_complex, ++ nargout, retval, Control, InfoOut, status, do_info) ; ++ return retval; ++ } ++ ++ if (have_User_Qinit) ++ delete [] Qinit; ++ ++ // report the Symbolic object ++ ++ if (A_is_complex) ++ umfpack_zi_report_symbolic (Symbolic, Control_ptr) ; ++ else ++ umfpack_di_report_symbolic (Symbolic, Control_ptr) ; ++ ++ // perform numeric factorization, or just return symbolic factorization ++ ++ if (do_numeric) ++ { ++ // perform the numeric factorization ++ void *Numeric; ++ ++ if (A_is_complex) ++ status = umfpack_zi_numeric (Ap, Ai, Ax, NULL, Symbolic, &Numeric, ++ Control_ptr, Info) ; ++ else ++ status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, ++ Control_ptr, Info) ; ++ ++ // free the symbolic factorization ++ if (A_is_complex) ++ umfpack_zi_free_symbolic (&Symbolic) ; ++ else ++ umfpack_di_free_symbolic (&Symbolic) ; ++ ++ // report the Numeric object ++ if (status < 0) ++ { ++ umfpack_error ("numeric factorization failed", A_is_complex, ++ nargout, retval, Control, InfoOut, status, do_info); ++ return retval; ++ } ++ ++ if (A_is_complex) ++ (void) umfpack_zi_report_numeric (Numeric, Control_ptr) ; ++ else ++ (void) umfpack_di_report_numeric (Numeric, Control_ptr) ; ++ ++ // return the solution or the factorization ++ ++ if (do_solve) ++ { ++ int sys; ++ ComplexNDArray Xcmplx; ++ NDArray Xreal; ++ ++ // solve Ax=b or A'x'=b', and return just the solution x ++ ++#ifndef NO_TRANSPOSE_FORWARD_SLASH ++ if (transpose) ++ { ++ // A.'x.'=b.' gives the same x=b/A as solving A'x'=b' ++ // since C=A.' was factorized, solve with sys = UMFPACK_A ++ // since x and b are vectors, x.' and b.' are implicit ++ if (X_is_complex) ++ Xcmplx.resize (dim_vector (1, nn)); ++ else ++ Xreal.resize (dim_vector (1, nn)); ++ } ++ else ++ { ++ if (X_is_complex) ++ Xcmplx.resize (dim_vector (nn, 1)); ++ else ++ Xreal.resize (dim_vector (nn, 1)); ++ } ++ ++ sys = UMFPACK_A ; ++#else ++ if (transpose) ++ { ++ // If A is real, A'x=b is the same as A.'x=b. ++ // x and b are vectors, so x and b are the same as x' and b'. ++ // If A is complex, then A.'x.'=b.' gives the same solution x ++ // as the complex conjugate transpose. If we used the A'x=b ++ // option in umfpack_*_solve, we would have to form b' on ++ // input and x' on output (negating the imaginary part). ++ // We can save this work by just using the A.'x=b option in ++ // umfpack_*_solve. Then, forming x.' and b.' is implicit, ++ // since x and b are just vectors anyway. ++ // In both cases, the system to solve is A.'x=b ++ if (X_is_complex) ++ Xcmplx.resize (dim_vector (1, nn)); ++ else ++ Xreal.resize (dim_vector (1, nn)); ++ ++ sys = UMFPACK_Aat ; ++ } ++ else ++ { ++ if (X_is_complex) ++ Xcmplx.resize (dim_vector (nn, 1)); ++ else ++ Xreal.resize (dim_vector (nn, 1)); ++ sys = UMFPACK_A ; ++ } ++#endif ++ ++ // print the right-hand-side, B ++ if (print_level >= 3) ++ octave_stdout << "\nright-hand side, b: "; ++ ++ if (B_is_complex) ++ (void) umfpack_zi_report_vector (nn, Bx, NULL, Control_ptr) ; ++ else ++ (void) umfpack_di_report_vector (nn, Bx, Control_ptr) ; ++ ++ // solve the system ++ double * Xx; ++ if (X_is_complex) ++ Xx = X_CAST (double *, Xcmplx.fortran_vec ()); ++ else ++ Xx = Xreal.fortran_vec (); ++ status2 = UMFPACK_OK ; ++ ++ if (A_is_complex) ++ { ++ if (!B_is_complex) ++ { ++ OCTAVE_LOCAL_BUFFER (double, Bz, nn); ++ for (int i = 0; i < nn; i++) ++ Bz[i] = 0.; ++ ++ status = umfpack_zi_solve (sys, Ap, Ai, Ax, NULL, Xx, NULL, ++ Bx, Bz, Numeric, Control_ptr, ++ Info); ++ } ++ else ++ status = umfpack_zi_solve (sys, Ap, Ai, Ax, NULL, Xx, NULL, ++ Bx, NULL, Numeric, Control_ptr, ++ Info); ++ } ++ else ++ { ++ if (B_is_complex) ++ { ++ // Ax=b when b is complex and A is sparse can be split ++ // into two systems, A*xr=br and A*xi=bi, where r denotes ++ // the real part and i the imaginary part of x and b. ++ OCTAVE_LOCAL_BUFFER (double, Tx, nn); ++ OCTAVE_LOCAL_BUFFER (double, Tz, nn); ++ ++ status = umfpack_di_solve (sys, Ap, Ai, Ax, Tx, Bx, ++ Numeric, Control_ptr, Info); ++ status2 = umfpack_di_solve (sys, Ap, Ai, Ax, Tz, Bx, ++ Numeric, Control_ptr, Info) ; ++ ++ for (int i = 0; i < nn; i++) ++ Xcmplx (i) = Complex (Tx[i], Tz[i]); ++ } ++ else ++ status = umfpack_di_solve (sys, Ap, Ai, Ax, Xx, Bx, ++ Numeric, Control_ptr, Info); ++ } ++ ++ // free the Numeric object ++ if (A_is_complex) ++ umfpack_zi_free_numeric (&Numeric) ; ++ else ++ umfpack_di_free_numeric (&Numeric) ; ++ ++ // check error status ++ if (status < 0 || status2 < 0) ++ { ++ umfpack_error ("solve failed", A_is_complex, nargout, ++ retval, Control, InfoOut, status, do_info) ; ++ return retval; ++ } ++ ++ // print the solution, X ++ if (print_level >= 3) ++ octave_stdout << "\nsolution, x: "; ++ ++ if (X_is_complex) ++ (void) umfpack_zi_report_vector (nn, Xx, NULL, Control_ptr); ++ else ++ (void) umfpack_di_report_vector (nn, Xx, Control_ptr); ++ ++ // warn about singular or near-singular matrices ++ // no warning is given if Control (1) is zero ++ if (Control (UMFPACK_PRL) >= 1) ++ { ++ if (status == UMFPACK_WARNING_singular_matrix) ++ { ++ warning ("matrix is singular"); ++ warning ("Try increasing Control (%d) and Control (%d).", ++ 1+UMFPACK_PIVOT_TOLERANCE, ++ 1+UMFPACK_SYM_PIVOT_TOLERANCE); ++ warning ("(Suppress this warning with Control (%d) = 0.)", ++ 1+UMFPACK_PRL); ++ } ++ else if (InfoOut (UMFPACK_RCOND) < DBL_EPSILON) ++ { ++ warning ("matrix is nearly singular, rcond = %g", ++ InfoOut (UMFPACK_RCOND)); ++ warning ("Try increasing Control (%d) and Control (%d).", ++ 1+UMFPACK_PIVOT_TOLERANCE, ++ 1+UMFPACK_SYM_PIVOT_TOLERANCE); ++ warning ("(Suppress this warning with Control (%d) = 0.)", ++ 1+UMFPACK_PRL); ++ } ++ } ++ ++ // Setup the return value ++ if (X_is_complex) ++ retval (0) = octave_value (Xcmplx); ++ else ++ retval (0) = octave_value (Xreal); ++ } ++ else ++ { ++ // get L, U, P, Q, and r ++ int lnz, unz, ignore1, ignore2, ignore3; ++ ++ if (A_is_complex) ++ status = umfpack_zi_get_lunz (&lnz, &unz, &ignore1, &ignore2, ++ &ignore3, Numeric) ; ++ else ++ status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, ++ &ignore3, Numeric) ; ++ ++ if (status < 0) ++ { ++ if (A_is_complex) ++ umfpack_zi_free_numeric (&Numeric) ; ++ else ++ umfpack_di_free_numeric (&Numeric) ; ++ ++ umfpack_error ("extracting LU factors failed", A_is_complex, ++ nargout, retval, Control, InfoOut, status, ++ do_info); ++ return retval; ++ } ++ ++ // avoid malloc of zero-sized arrays ++ lnz = MAX (lnz, 1) ; ++ unz = MAX (unz, 1) ; ++ ++ // get space for the *** ROW *** form of L ++ SparseMatrix Lreal; ++ SparseComplexMatrix Limag; ++ int *Ltp, *Ltj; ++ double *Ltx; ++ if (A_is_complex) ++ { ++ Limag = SparseComplexMatrix (n_inner, n_row, lnz); ++ Ltp = Limag.cidx (); ++ Ltj = Limag.ridx (); ++ Ltx = X_CAST (double *, Limag.data ()); ++ } ++ else ++ { ++ Lreal = SparseMatrix (n_inner, n_row, lnz); ++ Ltp = Lreal.cidx (); ++ Ltj = Lreal.ridx (); ++ Ltx = Lreal.data (); ++ } ++ ++ // create permanent copy of the output matrix U ++ int *Up, *Ui; ++ double *Ux; ++ SparseMatrix Ureal; ++ SparseComplexMatrix Uimag; ++ ++ if (A_is_complex) ++ { ++ Uimag = SparseComplexMatrix (n_inner, n_col, unz); ++ Up = Uimag.cidx (); ++ Ui = Uimag.ridx (); ++ Ux = X_CAST (double *, Uimag.data ()); ++ } ++ else ++ { ++ Ureal = SparseMatrix (n_inner, n_col, unz); ++ Up = Ureal.cidx (); ++ Ui = Ureal.ridx (); ++ Ux = Ureal.data (); ++ } ++ ++ // temporary space for the integer permutation vectors ++ OCTAVE_LOCAL_BUFFER (int, P, n_row); ++ OCTAVE_LOCAL_BUFFER (int, Q, n_col); ++ ++ // get scale factors, if requested ++ status2 = UMFPACK_OK ; ++ SparseMatrix Rsout; ++ double * Rs; ++ if (!no_scale) ++ { ++ // create a diagonal sparse matrix for the scale factors ++ Rsout = SparseMatrix (n_row, n_row, n_row); ++ for (int i = 0 ; i < n_row ; i++) ++ { ++ Rsout.cidx (i) = i; ++ Rsout.ridx (i) = i; ++ } ++ Rsout.cidx (n_row) = n_row; ++ Rs = Rsout.data (); ++ } ++ else ++ Rs = (double *) NULL ; ++ ++ // get Lt, U, P, Q, and Rs from the numeric object ++ int do_recip; ++ if (A_is_complex) ++ { ++ status = umfpack_zi_get_numeric (Ltp, Ltj, Ltx, NULL, Up, Ui, ++ Ux, NULL, P, Q, ++ (double *) NULL, ++ (double *) NULL, ++ &do_recip, Rs, Numeric) ; ++ umfpack_zi_free_numeric (&Numeric) ; ++ } ++ else ++ { ++ status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Ui, ++ Ux, P, Q, (double *) NULL, ++ &do_recip, Rs, Numeric) ; ++ umfpack_di_free_numeric (&Numeric) ; ++ } ++ ++ if (!no_scale) ++ retval (4) = octave_vale (Rsout); ++ ++ // for the oct-file, -DNRECIPROCAL must be set, ++ // so do_recip must be FALSE ++ ++ if (status < 0 || status2 < 0 || do_recip) ++ { ++ umfpack_error ("extracting LU factors failed", A_is_complex, ++ nargout, retval, Control, InfoOut, status, ++ do_info); ++ return retval; ++ } ++ ++ if (A_is_complex) ++ retval (1) = octave_value (Uimag); ++ else ++ retval (1) = octave_valye (Ureal); ++ ++ // create sparse permutation matrix for P ++ SparseMatrix Pout (n_row, n_row, n_row); ++ for (int k = 0 ; k < n_row ; k++) ++ { ++ Pout.cidx (k) = k ; ++ Pout.ridx (P [k]) = k; ++ Pout.data (k) = 1; ++ } ++ Pout.cidx (n_row) = n_row; ++ retval (2) = octave_value (Pout); ++ ++ // create sparse permutation matrix for Q ++ SparseMatrix Qout (n_col, n_col, n_col); ++ for (int k = 0 ; k < n_col ; k++) ++ { ++ Qout.cidx (k) = k ; ++ Qout.ridx (k) = Q[k]; ++ Qout.data (k) = 1; ++ } ++ Qout.cidx (n_col) = n_col; ++ retval (3) = octave_value (Qout); ++ ++ // permanent copy of L ++ if (A_is_complex) ++ retval (0) = octave_value (Limag.transpose()); ++ else ++ retval (0) = octave_value (Lreal.transpose()); ++ ++ if (status < 0) ++ { ++ umfpack_error ("constructing L failed", A_is_complex, ++ nargout, retval, Control, InfoOut, status, ++ do_info) ; ++ return octave_value (); ++ } ++ ++ // print L, U, P, and Q ++ if (A_is_complex) ++ { ++ if (print_level >= 3) ++ { ++ octave_stdout << "\nL: "; ++ int *Lp = Limag.cidx (); ++ int *Li = Limag.ridx (); ++ double *Lx = X_CAST (double *, Limag.data ()); ++ ++ (void) umfpack_zi_report_matrix (n_row, n_inner, Lp, Li, ++ Lx, NULL, 1, Control_ptr) ; ++ } ++ ++ if (print_level >= 3) ++ octave_stdout << "\nU: "; ++ (void) umfpack_zi_report_matrix (n_inner, n_col, Up, Ui, ++ Ux, NULL, 1, Control_ptr) ; ++ if (print_level >= 3) ++ octave_stdout << "\nP: "; ++ (void) umfpack_zi_report_perm (n_row, P, Control_ptr); ++ if (print_level >= 3) ++ octave_stdout << "\nQ: "; ++ (void) umfpack_zi_report_perm (n_col, Q, Control_ptr); ++ } ++ else ++ { ++ if (print_level >= 3) ++ { ++ int *Lp = Lreal.cidx (); ++ int *Li = Lreal.ridx (); ++ double *Lx = Lreal.data (); ++ octave_stdout << "\nL: "; ++ (void) umfpack_di_report_matrix (n_row, n_inner, Lp, Li, ++ Lx, 1, Control_ptr); ++ } ++ ++ if (print_level >= 3) ++ octave_stdout << "\nU: "; ++ (void) umfpack_di_report_matrix (n_inner, n_col, Up, Ui, ++ Ux, 1, Control_ptr); ++ if (print_level >= 3) ++ octave_stdout << "\nP: "; ++ (void) umfpack_di_report_perm (n_row, P, Control_ptr); ++ if (print_level >= 3) ++ octave_stdout << "\nQ: "; ++ (void) umfpack_di_report_perm (n_col, Q, Control_ptr); ++ } ++ } ++ } ++ else ++ { ++ // return the symbolic factorization ++ int ignore1, ignore2, ignore3; ++ OCTAVE_LOCAL_BUFFER (int, Q, n_col); ++ OCTAVE_LOCAL_BUFFER (int, P, n_row); ++ OCTAVE_LOCAL_BUFFER (int, Front_npivcol, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Front_parent, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Front_1strow, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Front_leftmostdesc, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Chain_start, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Chain_maxrows, nn + 1); ++ OCTAVE_LOCAL_BUFFER (int, Chain_maxcols, nn + 1); ++ ++ int nz, nfronts, nchains; ++ ++ if (A_is_complex) ++ { ++ status = umfpack_zi_get_symbolic (&ignore1, &ignore2, &ignore3, ++ &nz, &nfronts, &nchains, P, Q, ++ Front_npivcol, Front_parent, ++ Front_1strow, ++ Front_leftmostdesc, ++ Chain_start, Chain_maxrows, ++ Chain_maxcols, Symbolic) ; ++ umfpack_zi_free_symbolic (&Symbolic) ; ++ } ++ else ++ { ++ status = umfpack_di_get_symbolic (&ignore1, &ignore2, &ignore3, ++ &nz, &nfronts, &nchains, P, Q, ++ Front_npivcol, Front_parent, ++ Front_1strow, ++ Front_leftmostdesc, ++ Chain_start, Chain_maxrows, ++ Chain_maxcols, Symbolic) ; ++ umfpack_di_free_symbolic (&Symbolic) ; ++ } ++ ++ if (status < 0) ++ { ++ umfpack_error ("extracting symbolic factors failed", ++ A_is_complex, nargout, retval, Control, ++ InfoOut, status, do_info) ; ++ return retval; ++ } ++ ++ // create sparse permutation matrix for P ++ SparseMatrix Pout (n_row, n_row, n_row); ++ for (int k = 0 ; k < n_row ; k++) ++ { ++ Pout.cidx (k) = k; ++ Pout.ridx (P [k]) = k; ++ Pout.data (k) = 1; ++ } ++ Pout.cidx (n_row) = n_row; ++ retval (0) = octave_value (Pout); ++ ++ // create sparse permutation matrix for Q ++ SparseMatrix Qout (n_col, n_col, n_col); ++ for (int k = 0 ; k < n_col ; k++) ++ { ++ Qout.cidx (k) = k; ++ Qout.ridx (k) = Q[k]; ++ Qout.data (k) = 1; ++ } ++ Qout.cidx (n_col) = n_col; ++ retval (1) = octave_value (Qout); ++ ++ // create Fr ++ Matrix Frout (nfronts + 1, 4); ++ for (int i = 0 ; i <= nfronts ; i++) ++ { ++ // convert parent, 1strow, and leftmostdesc to 1-based ++ Frout (i, 0) = (double) (Front_npivcol [i]) ; ++ Frout (i, 1) = (double) (Front_parent [i] + 1) ; ++ Frout (i, 2) = (double) (Front_1strow [i] + 1) ; ++ Frout (i, 3) = (double) (Front_leftmostdesc [i] + 1) ; ++ } ++ retval (2) = octave_value (Frout); ++ ++ // create Ch ++ Matrix Chout (nchains + 1, 3); ++ for (int i = 0 ; i <= nchains ; i++) ++ { ++ // convert to 1-based ++ Chout (i, 0) = (double) (Chain_start [i] + 1) ; ++ Chout (i, 1) = (double) (Chain_maxrows [i]) ; ++ Chout (i, 2) = (double) (Chain_maxcols [i]) ; ++ } ++ Chout (0, nchains) = (double) Chain_start [nchains] + 1 ; ++ Chout (1, nchains) = 0.; ++ Chout (2, nchains) = 0.; ++ retval (3) = octave_value (Chout); ++ } ++ ++ // report Info ++ if (A_is_complex) ++ umfpack_zi_report_info (Control_ptr, Info); ++ else ++ umfpack_di_report_info (Control_ptr, Info); ++ ++ if (do_info > 0) ++ retval (do_info) = InfoOut; ++ ++ return retval; ++} ++ ++/* ++;;; Local Variables: *** ++;;; mode: C++ *** ++;;; End: *** ++*/ +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_demo.m UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_demo.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,191 @@ ++function umfpack_demo ++% UMFPACK DEMO ++% ++% A demo of UMFPACK for OCTAVE. ++% ++% See also umfpack, umfpack_make, umfpack_details, umfpack_report, ++% and umfpack_simple. ++ ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. Type umfpack_details for License. ++ ++%------------------------------------------------------------------------------- ++% get default control parameters ++%------------------------------------------------------------------------------- ++ ++control = umfpack ; ++fprintf ('\nEnter the printing level for UMFPACK''s output statistics:\n') ; ++fprintf ('0: none, 1: errors only, 2: statistics, 4: print some of outputs\n') ; ++c = input ('5: print all output [default is 1]: ') ; ++if (isempty (c)) ++ c = 1 ; ++end ++control (1) = c ; ++ ++%------------------------------------------------------------------------------- ++% solve a simple system ++%------------------------------------------------------------------------------- ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('Factor and solve a small system, Ax=b, using default parameters\n') ; ++if (control (1) > 1) ++ fprintf ('(except for verbose printing enabled)\n') ; ++end ++ ++load west0067 ; ++A = Problem.A ; ++n = size (A, 1) ; ++b = rand (n, 1) ; ++ ++fprintf ('Solving Ax=b via UMFPACK:\n') ; ++[xu, info] = umfpack (A, '\\', b, control) ; ++x = xu ; ++ ++fprintf ('Solving Ax=b via OCTAVE:\n') ; ++xm = A\b ; ++x = xm ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (xu - xm, Inf)) ; ++ ++%------------------------------------------------------------------------------- ++% spy the results ++%------------------------------------------------------------------------------- ++ ++figure (1) ; ++clf ++ ++subplot (2,3,1) ++title ('The matrix A') ; ++spy (A) ++ ++subplot (2,3,2) ++[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ; ++title ('Supernodal column elimination tree') ; ++%% Disable for now !! ++%% treeplot (Fr (1:end-1,2)') ; ++ ++subplot (2,3,3) ++title ('A, with initial row and column order') ; ++spy (P1 * A * Q1) ++ ++subplot (2,3,4) ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('\nFactorizing [L, U, P, Q, R] = umfpack (A)\n') ; ++[L, U, P, Q, R] = umfpack (A) ; ++title ('A, with final row/column order') ; ++spy (P*A*Q) ++ ++fprintf ('\nP * (R\\A) * Q - L*U should be zero:\n') ; ++fprintf ('norm (P*(R\\A)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... ++ norm (P * (R\A) * Q - L*U, 1), lu_normest (P * (R\A) * Q, L, U)) ; ++ ++fprintf ('\nSolution to Ax=b via UMFPACK factorization:\n') ; ++fprintf ('x = Q * (U \\ (L \\ (P * (R \\ b))))\n') ; ++xu = Q * (U \ (L \ (P * (R \ b)))) ; ++x = xu ; ++ ++fprintf ('\nUMFPACK flop count: %d\n', luflop (L, U)) ; ++ ++subplot (2,3,5) ++title ('UMFPACK LU factors') ; ++spy (spones (L) + spones (U)) ++ ++subplot (2,3,6) ++fprintf ('\nFactorizing [L, U, P] = lu (A (:, q))\n') ; ++try ++ q = colamd (A) ; ++catch ++ fprintf ('\n *** colamd not found, using colmmd instead *** \n') ; ++ q = colmmd (A) ; ++end ++[L, U, P] = lu (A (:,q)) ; ++title ('OCTAVE LU factors') ; ++spy (spones (L) + spones (U)) ++ ++fprintf ('\nSolution to Ax=b via OCTAVE factorization:\n') ; ++fprintf ('x = U \\ (L \\ (P * b)) ; x (q) = x ;\n') ; ++xm = U \ (L \ (P * b)) ; ++xm (q) = xm ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (xu - xm, Inf)) ; ++ ++fprintf ('\nOCTAVE LU flop count: %d\n', luflop (L, U)) ; ++ ++%------------------------------------------------------------------------------- ++% solve A'x=b ++%------------------------------------------------------------------------------- ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('Solve A''x=b:\n') ; ++ ++fprintf ('Solving A''x=b via UMFPACK:\n') ; ++[xu, info] = umfpack (b', '/', A, control) ; ++xu = xu' ; ++ ++fprintf ('Solving A''x=b via OCTAVE:\n') ; ++xm = (b'/A)' ; ++x = xm ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (xu - xm, Inf)) ; ++ ++%------------------------------------------------------------------------------- ++% factor A' and then solve Ax=b using the factors of A' ++%------------------------------------------------------------------------------- ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('Compute C = A'', and compute the LU factorization of C.\n') ; ++fprintf ('Factorizing A'' can sometimes be better than factorizing A itself\n'); ++fprintf ('(less work and memory usage). Solve C''x=b; the solution is the\n') ; ++fprintf ('same as the solution to Ax=b for the original A.\n'); ++ ++C = A' ; ++ ++% factorize C (P,Q) = L*U ++[L, U, P, Q, R, info] = umfpack (C, control) ; ++ ++fprintf ('\nP * (R\\C) * Q - L*U should be zero:\n') ; ++fprintf ('norm (P*(R\\C)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... ++ norm (P * (R\C) * Q - L*U, 1), lu_normest (P * (R\C) * Q, L, U)) ; ++ ++fprintf ('\nSolution to Ax=b via UMFPACK, using the factors of C:\n') ; ++fprintf ('x = R \\ (P'' * (L'' \\ (U'' \\ (Q'' * b)))) ;\n') ; ++xu = R \ (P' * (L' \ (U' \ (Q' * b)))) ; ++x = xu ; ++ ++fprintf ('Solution to Ax=b via OCTAVE:\n') ; ++xm = A\b ; ++x = xm ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (xu - xm, Inf)) ; ++ ++%------------------------------------------------------------------------------- ++% solve Ax=B ++%------------------------------------------------------------------------------- ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('\nSolve AX=B, where B is n-by-10, and sparse\n') ; ++B = sprandn (n, 10, 0.05) ; ++XU = umfpack_solve (A, '\\', B, control) ; ++XM = A\B ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (XU - XM, Inf)) ; ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('\nSolve AX=B, where B is n-by-10, and sparse, using umfpack_btf\n') ; ++XU = umfpack_btf (A, B, control) ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (XU - XM, Inf)) ; ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('\nSolve A''X=B, where B is n-by-10, and sparse\n') ; ++XU = umfpack_solve (B', '/', A, control) ; ++XM = B'/A ; ++ ++fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... ++ norm (XU - XM, Inf)) ; +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_demo.m.out UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m.out +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_demo.m.out 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m.out 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,72 @@ ++>> umfpack_demo ++ ++Enter the printing level for UMFPACK's output statistics: ++0: none, 1: errors only, 2: statistics, 4: print some of outputs ++5: print all output [default is 1]: ++ ++-------------------------------------------------------------- ++Factor and solve a small system, Ax=b, using default parameters ++Solving Ax=b via UMFPACK: ++Solving Ax=b via MATLAB: ++Difference between UMFPACK and MATLAB solution: 1.24345e-14 ++ ++-------------------------------------------------------------- ++ ++Factorizing [L, U, P, Q, R] = umfpack (A) ++ ++P * (R\A) * Q - L*U should be zero: ++norm (P*(R\A)*Q - L*U, 1) = 4.2068e-16 (exact) 3.74627e-16 (estimated) ++ ++Solution to Ax=b via UMFPACK factorization: ++x = Q * (U \ (L \ (P * (R \ b)))) ++ ++UMFPACK flop count: 2362 ++ ++Factorizing [L, U, P] = lu (A (:, q)) ++If you are using a version of MATLAB prior to V6.0, then the ++following statement (q = colamd (A)) may fail. Either download ++colamd from http://www.cise.ufl.edu/research/sparse, upgrade to ++MATLAB V6.0 or later, or replace the statement with ++q = colmmd (A) ; ++ ++Solution to Ax=b via MATLAB factorization: ++x = U \ (L \ (P * b)) ; x (q) = x ; ++Difference between UMFPACK and MATLAB solution: 1.37668e-14 ++ ++MATLAB LU flop count: 3164 ++ ++-------------------------------------------------------------- ++Solve A'x=b: ++Solving A'x=b via UMFPACK: ++Solving A'x=b via MATLAB: ++Difference between UMFPACK and MATLAB solution: 3.10862e-15 ++ ++-------------------------------------------------------------- ++Compute C = A', and compute the LU factorization of C. ++Factorizing A' can sometimes be better than factorizing A itself ++(less work and memory usage). Solve C'x=b; the solution is the ++same as the solution to Ax=b for the original A. ++ ++P * (R\C) * Q - L*U should be zero: ++norm (P*(R\C)*Q - L*U, 1) = 1.31839e-16 (exact) 6.41848e-17 (estimated) ++ ++Solution to Ax=b via UMFPACK, using the factors of C: ++x = R \ (P' * (L' \ (U' \ (Q' * b)))) ; ++Solution to Ax=b via MATLAB: ++Difference between UMFPACK and MATLAB solution: 1.77636e-14 ++ ++-------------------------------------------------------------- ++ ++Solve AX=B, where B is n-by-10, and sparse ++Difference between UMFPACK and MATLAB solution: 2.88198e-14 ++ ++-------------------------------------------------------------- ++ ++Solve AX=B, where B is n-by-10, and sparse, using umfpack_btf ++Difference between UMFPACK and MATLAB solution: 9.79736e-14 ++ ++-------------------------------------------------------------- ++ ++Solve A'X=B, where B is n-by-10, and sparse ++Difference between UMFPACK and MATLAB solution: 1.05244e-13 ++>> diary off +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_make.m UMFPACK/UMFPACK/OCTAVE/umfpack_make.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_make.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_make.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,356 @@ ++function umfpack_make ++% UMFPACK_MAKE ++% ++% Compiles the UMFPACK mexFunction and then runs a simple demo. ++% ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. Type umfpack_details for License. ++% ++% See also: umfpack, umfpack_details, umfpack_report, umfpack_demo, and ++% umfpack_simple. ++ ++help umfpack_make ++ ++fprintf ('\n--------------------------------------------------------------\n') ; ++fprintf ('Now compiling the UMFPACK and AMD mexFunctions.\n') ; ++fprintf ('--------------------------------------------------------------\n') ; ++ ++try ++ % ispc does not appear in MATLAB 5.3 ++ pc = ispc ; ++catch ++ % if ispc fails, assume we aren't on a Windows PC. ++ pc = 0 ; ++end ++ ++obj = 'o' ; ++blas_lib = '' ; ++if (pc) ++ obj = 'obj' ; ++end ++ ++%------------------------------------------------------------------------------- ++% BLAS option ++%------------------------------------------------------------------------------- ++ ++msg = [ ... ++ '\nUsing the BLAS is faster, but might not compile correctly.\n', ... ++ 'If you get an error stating that dgemm, dgemv, dger, zgemm,\n', ... ++ 'zgemv, and/or zger are not defined, then recompile without the\n', ... ++ 'BLAS. You can ignore warnings that these routines are implicitly\n', ... ++ 'declared.\n\nPlease select one of the following options: \n', ... ++ ' 1: attempt to compile with the BLAS (default)\n', ... ++ ' 2: do not use the BLAS\n'] ; ++fprintf (msg) ; ++blas = input (': ') ; ++if (isempty (blas)) ++ blas = 1 ; ++end ++if (blas == 1) ++ % try to link to MATLAB's built-in BLAS ++ blas = '' ; ++ if (pc) ++ % the default lcc compiler needs this library to access the BLAS ++ blas_lib = ' libmwlapack.lib' ; ++ msg = [ ... ++ '\nCheck to see if you have a file called libmwlapack.lib in the\n', ... ++ '\\extern\\lib\\win32\\lcc\\ directory, where is ', ... ++ 'the\ndirectory where MATLAB is installed. If a file of that ', ... ++ 'name is already\nthere, then you don''t have to do anything. ', ... ++ 'Otherwise, you must first\ncopy the libmwlapack.lib file from ', ... ++ 'the umfpack\\lcc_lib\\ directory to the\n', ... ++ '\\extern\\lib\\win32\\lcc\\ directory. Next, type\n\n', ... ++ ' mex -setup\n\n', ... ++ 'at the MATLAB prompt, and ask MATLAB to select the lcc compiler. ',... ++ 'You can skip\nall of this if you have already done it, or have ', ... ++ 'configured mex to use\na different compiler. If you are using ', ... ++ 'Norton anti-virus software on Windows\n98SE, then you need to ', ... ++ 'exit MATLAB, turn off virus checking, and restart MATLAB\n', ... ++ 'before you can use the mex command or compile UMFPACK.\n', ... ++ 'You may also need to turn off virus checking in other cases.\n', ... ++ '\nHit enter to continue, or type control-C if you do not wish to '] ; ++ fprintf (msg) ; ++ input ('proceed: ') ; ++ end ++ fprintf ('\nUsing the BLAS (recommended).\n') ; ++else ++ % No BLAS ++ fprintf ('\nNot using the BLAS. UMFPACK will be slow.\n') ; ++ blas = ' -DNBLAS' ; ++end ++ ++%------------------------------------------------------------------------------- ++% -DNUTIL option (using utMalloc or mxMalloc) ++%------------------------------------------------------------------------------- ++ ++utils = '' ; ++ ++if (~pc) ++ msg = [ ... ++ '--------------------------------------------------------------\n', ... ++ '\nUMFPACK uses MATLAB''s memory allocation routines. The internal', ... ++ '\nutMalloc, utFree, and utRealloc allow for better use of memory,', ... ++ '\nbut they are internal utility routines that are not documented.\n', ... ++ 'Thus, they might not always work. Using mxMalloc, mxFree, and\n', ... ++ 'mxRealloc works, but UMFPACK might run out of memory when solving\n', ... ++ 'problems that it could otherwise solve. Try using the default.\n', ... ++ 'If you get an error stating that utMalloc, utFree, and/or\n', ... ++ 'utRealloc are not defined, then recompile with the mx* routines.\n', ... ++ '\nPlease select one of the following options:\n', ... ++ ' 1: attempt to use the ut* routines (default)\n', ... ++ ' 2: use the standard mx* routines\n'] ; ++ fprintf (msg) ; ++ utils = input (': ') ; ++ if (isempty (utils)) ++ utils = 1 ; ++ end ++ if (utils == 2) ++ fprintf ('\nNot using utMalloc, utFree, or utRealloc\n') ; ++ utils = ' -DNUTIL' ; ++ else ++ fprintf ('\nUsing utMalloc, utFree, and utRealloc\n') ; ++ utils = '' ; ++ end ++end ++ ++%------------------------------------------------------------------------------- ++% -DNPOSIX option (for sysconf and times timer routines) ++%------------------------------------------------------------------------------- ++ ++posix = '' ; ++ ++if (~pc) ++ msg = [ ... ++ '--------------------------------------------------------------\n', ... ++ '\nUMFPACK can use the POSIX routines sysconf () and times ()\n', ... ++ 'to provide CPU time and wallclock time statistics. If you do not\n', ... ++ 'have a POSIX-compliant operating system, then UMFPACK won''t\n', ... ++ 'compile. If you don''t know which option to pick, try the\n', ... ++ 'default. If you get an error saying that sysconf and/or times\n', ... ++ 'are not defined, then recompile with the non-POSIX option.\n', ... ++ '\nPlease select one of the following options:\n', ... ++ ' 1: use POSIX sysconf and times routines (default)\n', ... ++ ' 2: do not use POSIX routines\n'] ; ++ fprintf (msg) ; ++ posix = input (': ') ; ++ if (isempty (posix)) ++ posix = 1 ; ++ end ++ if (posix == 2) ++ fprintf ('\nNot using POSIX sysconf and times routines.\n') ; ++ posix = ' -DNPOSIX' ; ++ else ++ fprintf ('\nUsing POSIX sysconf and times routines.\n') ; ++ posix = '' ; ++ end ++end ++ ++%------------------------------------------------------------------------------- ++% mex command ++%------------------------------------------------------------------------------- ++ ++umfdir = sprintf ('..%sSource%s', filesep, filesep) ; ++amddir = sprintf ('..%s..%sAMD%sSource%s', filesep, filesep, filesep, filesep) ; ++incdir = sprintf ( ... ++' -I..%sInclude -I..%sSource -I..%s..%sAMD%sInclude -I..%s..%sAMD%sSource', ... ++filesep,filesep, filesep, filesep, filesep, filesep, filesep, filesep) ; ++ ++mx = sprintf ('mex -inline -O%s%s%s%s', blas, utils, posix, incdir) ; ++msg = [ ... ++ '--------------------------------------------------------------\n', ... ++ '\nCompile options:\n%s\nNow compiling. Please wait.\n'] ; ++fprintf (msg, mx) ; ++ ++% The following is adapted from GNUmakefile ++ ++%------------------------------------------------------------------------------- ++% source files ++%------------------------------------------------------------------------------- ++ ++% non-user-callable umf_*.[ch] files: ++umfch = { 'assemble', 'blas3_update', ... ++ 'build_tuples', 'create_element', ... ++ 'dump', 'extend_front', 'garbage_collection', ... ++ 'get_memory', 'init_front', 'kernel', ... ++ 'kernel_init', 'kernel_wrapup', ... ++ 'local_search', 'lsolve', 'ltsolve', ... ++ 'mem_alloc_element', 'mem_alloc_head_block', ... ++ 'mem_alloc_tail_block', 'mem_free_tail_block', ... ++ 'mem_init_memoryspace', ... ++ 'report_vector', 'row_search', 'scale_column', ... ++ 'set_stats', 'solve', 'symbolic_usage', 'transpose', ... ++ 'tuple_lengths', 'usolve', 'utsolve', 'valid_numeric', ... ++ 'valid_symbolic', 'grow_front', 'start_front', '2by2', ... ++ 'store_lu', 'scale' } ; ++ ++% non-user-callable umf_*.[ch] files, int versions only (no real/complex): ++umfint = { 'analyze', 'apply_order', 'colamd', 'free', 'fsize', ... ++ 'is_permutation', 'malloc', 'realloc', 'report_perm', ... ++ 'singletons' } ; ++ ++% non-user-callable and user-callable amd_*.[ch] files (int versions only): ++amd = { 'aat', '1', '2', 'dump', 'postorder', 'post_tree', 'defaults', ... ++ 'order', 'control', 'info', 'valid' } ; ++ ++% user-callable umfpack_*.[ch] files (real/complex): ++user = { 'col_to_triplet', 'defaults', 'free_numeric', ... ++ 'free_symbolic', 'get_numeric', 'get_lunz', ... ++ 'get_symbolic', 'numeric', 'qsymbolic', ... ++ 'report_control', 'report_info', 'report_matrix', ... ++ 'report_numeric', 'report_perm', 'report_status', ... ++ 'report_symbolic', 'report_triplet', ... ++ 'report_vector', 'solve', 'symbolic', ... ++ 'transpose', 'triplet_to_col', 'scale' ... ++ 'load_numeric', 'save_numeric', 'load_symbolic', 'save_symbolic' } ; ++ ++% user-callable umfpack_*.[ch], only one version ++generic = { 'timer', 'tictoc' } ; ++ ++M = cell (0) ; ++ ++%------------------------------------------------------------------------------- ++% Create the umfpack and amd mexFunctions for MATLAB (int versions only) ++%------------------------------------------------------------------------------- ++ ++for k = 1:length(umfint) ++ M = make (M, '%s -DDINT -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... ++ mx, umfint {k}, umfint {k}, 'm', obj, umfdir) ; ++end ++ ++rules = { [mx ' -DDINT'] , [mx ' -DZINT'] } ; ++kinds = { 'md', 'mz' } ; ++ ++for what = 1:2 ++ ++ rule = rules {what} ; ++ kind = kinds {what} ; ++ ++ M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s.%s', rule, 'ltsolve', 'lhsolve', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s.%s', rule, 'utsolve', 'uhsolve', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -DDO_MAP -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_map_nox.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_nomap_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_nomap_nox.%s', rule, 'triplet', 'triplet', kind, obj, ... ++ umfdir) ; ++ ++ M = make (M, '%s -DDO_MAP -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_map_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -DFIXQ -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_fixq.%s', rule, 'assemble', 'assemble', kind, obj, umfdir) ; ++ ++ M = make (M, '%s -DDROP -c %sumf_%s.c', 'umf_%s.%s', ... ++ 'umf_%s_%s_drop.%s', rule, 'store_lu', 'store_lu', kind, obj, umfdir) ; ++ ++ for k = 1:length(umfch) ++ M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... ++ rule, umfch {k}, umfch {k}, kind, obj, umfdir) ; ++ end ++ ++ M = make (M, '%s -DWSOLVE -c %sumfpack_%s.c', 'umfpack_%s.%s', ... ++ 'umfpack_%s_w%s.%s', rule, 'solve', 'solve', kind, obj, umfdir) ; ++ ++ for k = 1:length(user) ++ M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... ++ 'umfpack_%s_%s.%s', rule, user {k}, user {k}, kind, obj, umfdir) ; ++ end ++end ++ ++for k = 1:length(generic) ++ M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... ++ 'umfpack_%s_%s.%s', mx, generic {k}, generic {k}, 'm', obj, umfdir) ; ++end ++ ++%---------------------------------------- ++% AMD routines (int only) ++%---------------------------------------- ++ ++for k = 1:length(amd) ++ M = make (M, '%s -DDINT -c %samd_%s.c', 'amd_%s.%s', 'amd_%s_%s.%s', ... ++ mx, amd {k}, amd {k}, 'm', obj, amddir) ; ++end ++ ++%---------------------------------------- ++% compile the umfpack mexFunction ++%---------------------------------------- ++ ++C = sprintf ('%s -output umfpack umfpackmex.c', mx) ; ++for i = 1:length (M) ++ C = [C ' ' (M {i})] ; ++end ++C = [C ' ' blas_lib] ; ++cmd (C) ; ++ ++%---------------------------------------- ++% delete the object files ++%---------------------------------------- ++ ++for i = 1:length (M) ++ rmfile (M {i}) ; ++end ++ ++%---------------------------------------- ++% compile the luflop mexFunction ++%---------------------------------------- ++ ++cmd (sprintf ('%s -output luflop luflopmex.c', mx)) ; ++ ++fprintf ('\n\nCompilation has completed. Now trying the umfpack_simple demo.\n'); ++umfpack_simple ++ ++%------------------------------------------------------------------------------- ++% rmfile: delete a file, but only if it exists ++%------------------------------------------------------------------------------- ++ ++function rmfile (file) ++if (length (dir (file)) > 0) ++ delete (file) ; ++end ++ ++%------------------------------------------------------------------------------- ++% cpfile: copy the src file to the filename dst, overwriting dst if it exists ++%------------------------------------------------------------------------------- ++ ++function cpfile (src, dst) ++rmfile (dst) ++if (length (dir (src)) == 0) ++ help umfpack_make ++ error (sprintf ('File does not exist: %s\n', src)) ; ++end ++copyfile (src, dst) ; ++ ++%------------------------------------------------------------------------------- ++% mvfile: move the src file to the filename dst, overwriting dst if it exists ++%------------------------------------------------------------------------------- ++ ++function mvfile (src, dst) ++cpfile (src, dst) ; ++rmfile (src) ; ++ ++%------------------------------------------------------------------------------- ++% cmd: display and execute a command ++%------------------------------------------------------------------------------- ++ ++function cmd (s) ++fprintf ('.') ; ++eval (s) ; ++ ++%------------------------------------------------------------------------------- ++% make: execute a "make" command for a source file ++%------------------------------------------------------------------------------- ++ ++function M = make (M, s, src, dst, rule, file1, file2, kind, obj, srcdir) ++cmd (sprintf (s, rule, srcdir, file1)) ; ++src = sprintf (src, file1, obj) ; ++dst = sprintf (dst, kind, file2, obj) ; ++mvfile (src, dst) ; ++M {end + 1} = dst ; ++ +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_report.m UMFPACK/UMFPACK/OCTAVE/umfpack_report.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_report.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_report.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,346 @@ ++function umfpack_report (Control, Info) ++% UMFPACK_REPORT ++% ++% umfpack_report (Control, Info) ; ++% ++% Prints the current Control settings for umfpack, and the statistical ++% information returned by umfpack in the Info array. If Control is ++% an empty matrix, then the default control settings are printed. ++% ++% Control is 20-by-1, and Info is 90-by-1. Not all entries are used. ++% ++% Alternative usages: ++% ++% umfpack_report ([ ], Info) ; print the default control parameters ++% and the Info array. ++% umfpack_report (Control) ; print the control parameters only. ++% umfpack_report ; print the default control parameters ++% and an empty Info array. ++% ++% See also umfpack, umfpack_make, umfpack_details, ++% umfpack_demo, and umfpack_simple. ++ ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. See ../README for License. ++ ++%------------------------------------------------------------------------------- ++% get inputs, use defaults if input arguments not present ++%------------------------------------------------------------------------------- ++ ++% The contents of Control and Info are defined in umfpack.h ++if (nargin < 1) ++ Control = [] ; ++end ++if (nargin < 2) ++ Info = [] ; ++end ++if (isempty (Control)) ++ Control = umfpack ; ++end ++if (isempty (Info)) ++ Info = [ 0 (-ones (1, 89)) ] ; ++end ++ ++%------------------------------------------------------------------------------- ++% control settings ++%------------------------------------------------------------------------------- ++ ++fprintf ('\nUMFPACK Version 4.3: Control settings:\n\n') ; ++fprintf (' Control (1): print level: %d\n', Control (1)) ; ++fprintf (' Control (2): dense row parameter: %g\n', Control (2)) ; ++fprintf (' "dense" rows have > max (16, (%g)*16*sqrt(n_col)) entries\n', Control (2)) ; ++fprintf (' Control (3): dense column parameter: %g\n', Control (3)) ; ++fprintf (' "dense" columns have > max (16, (%g)*16*sqrt(n_row)) entries\n', Control (3)) ; ++fprintf (' Control (4): pivot tolerance: %g\n', Control (4)) ; ++fprintf (' Control (5): max block size for dense matrix kernels: %d\n', Control (5)) ; ++prstrat (' Control (6): strategy: %g ', Control (6)) ; ++fprintf (' Control (7): initial allocation ratio: %g\n', Control (7)) ; ++fprintf (' Control (8): max iterative refinement steps: %d\n', Control (8)) ; ++fprintf (' Control (13): 2-by-2 pivot tolerance: %g\n', Control (13)) ; ++fprintf (' Control (14): Q fixed during numeric factorization: %g ', Control (14)) ; ++if (Control (14) > 0) ++ fprintf ('(yes)\n') ; ++elseif (Control (14) < 0) ++ fprintf ('(no)\n') ; ++else ++ fprintf ('(auto)\n') ; ++end ++fprintf (' Control (15): AMD dense row/column parameter: %g\n', Control (15)) ; ++fprintf (' "dense" rows/columns in A+A'' have > max (16, (%g)*sqrt(n)) entries.\n', Control (15)) ; ++fprintf (' Only used if the AMD ordering is used.\n') ; ++fprintf (' Control (16): diagonal pivot tolerance: %g\n', Control (16)) ; ++fprintf (' Only used if diagonal pivoting is attempted.\n') ; ++ ++fprintf (' Control (17): scaling option: %g ', Control (17)) ; ++if (Control (17) == 0) ++ fprintf ('(none)\n') ; ++elseif (Control (17) == 2) ++ fprintf ('(scale the matrix by\n') ; ++ fprintf (' dividing each row by max. abs. value in each row)\n') ; ++else ++ fprintf ('(scale the matrix by\n') ; ++ fprintf (' dividing each row by sum of abs. values in each row)\n') ; ++end ++ ++fprintf (' Control (18): frontal matrix allocation ratio: %g\n', Control (18)) ; ++fprintf (' Control (19): drop tolerance: %g\n', Control (19)) ; ++fprintf (' Control (20): AMD and COLAMD aggressive absorption: %g ', Control (20)) ; ++yes_no (Control (20)) ; ++ ++% compile-time options: ++ ++fprintf ('\n The following options can only be changed at compile-time:\n') ; ++ ++if (Control (9) == 1) ++ fprintf (' Control (9): compiled to use the BLAS\n') ; ++else ++ fprintf (' Control (9): compiled without the BLAS\n') ; ++ fprintf (' (you will not get the best possible performance)\n') ; ++end ++ ++if (Control (10) == 1) ++ fprintf (' Control (10): compiled for MATLAB\n') ; ++elseif (Control (10) == 2) ++ fprintf (' Control (10): compiled for MATLAB\n') ; ++ fprintf (' Uses internal utMalloc, utFree, utRealloc, utPrintf\n') ; ++ fprintf (' utDivideComplex, and utFdlibm_hypot routines.\n') ; ++else ++ fprintf (' Control (10): not compiled for MATLAB\n') ; ++ fprintf (' Uses ANSI C malloc, free, realloc, and printf\n') ; ++ fprintf (' instead of mxMalloc, mxFree, mxRealloc, and mexPrintf.\n') ; ++ fprintf (' Printing will be in terms of 0-based matrix indexing,\n') ; ++ fprintf (' not 1-based as is expected in MATLAB. Diary output may\n') ; ++ fprintf (' not be properly recorded.\n') ; ++end ++ ++if (Control (11) == 2) ++ fprintf (' Control (11): uses POSIX times ( ) to get CPU time and wallclock time.\n') ; ++elseif (Control (11) == 1) ++ fprintf (' Control (11): uses getrusage to get CPU time.\n') ; ++else ++ fprintf (' Control (11): uses ANSI C clock to get CPU time.\n') ; ++ fprintf (' The CPU time may wrap around, type "help cputime".\n') ; ++end ++ ++if (Control (12) == 1) ++ fprintf (' Control (12): compiled with debugging enabled\n') ; ++ fprintf (' ###########################################\n') ; ++ fprintf (' ### This will be exceedingly slow! ########\n') ; ++ fprintf (' ###########################################\n') ; ++ if (Control (10) == 1) ++ fprintf (' Uses mxAssert.\n') ; ++ elseif (Control (10) == 2) ++ fprintf (' Uses utAssert.\n') ; ++ else ++ fprintf (' Uses ANSI C assert instead of mxAssert.\n') ; ++ end ++else ++ fprintf (' Control (12): compiled for normal operation (no debugging)\n') ; ++end ++ ++%------------------------------------------------------------------------------- ++% Info: ++%------------------------------------------------------------------------------- ++ ++if (nargin == 1) ++ return ++end ++ ++status = Info (1) ; ++fprintf ('\nUMFPACK status: Info (1): %d, ', status) ; ++ ++if (status == 0) ++ fprintf ('OK\n') ; ++elseif (status == 1) ++ fprintf ('WARNING matrix is singular\n') ; ++elseif (status == -1) ++ fprintf ('ERROR out of memory\n') ; ++elseif (status == -3) ++ fprintf ('ERROR numeric LU factorization is invalid\n') ; ++elseif (status == -4) ++ fprintf ('ERROR symbolic LU factorization is invalid\n') ; ++elseif (status == -5) ++ fprintf ('ERROR required argument is missing\n') ; ++elseif (status == -6) ++ fprintf ('ERROR n <= 0\n') ; ++elseif (status <= -7 & status >= -12 | status == -14) ++ fprintf ('ERROR matrix A is corrupted\n') ; ++elseif (status == -13) ++ fprintf ('ERROR invalid system\n') ; ++elseif (status == -15) ++ fprintf ('ERROR invalid permutation\n') ; ++elseif (status == -911) ++ fprintf ('ERROR internal error!\n') ; ++ fprintf ('Please report this error to Tim Davis (davis@cise.ufl.edu)\n') ; ++else ++ fprintf ('ERROR unrecognized error. Info array corrupted\n') ; ++end ++ ++fprintf (' (a -1 means the entry has not been computed):\n') ; ++ ++fprintf ('\n Basic statistics:\n') ; ++fprintf (' Info (2): %d, # of rows of A\n', Info (2)) ; ++fprintf (' Info (17): %d, # of columns of A\n', Info (17)) ; ++fprintf (' Info (3): %d, nnz (A)\n', Info (3)) ; ++fprintf (' Info (4): %d, Unit size, in bytes, for memory usage reported below\n', Info (4)) ; ++fprintf (' Info (5): %d, size of int (in bytes)\n', Info (5)) ; ++fprintf (' Info (6): %d, size of long (in bytes)\n', Info (6)) ; ++fprintf (' Info (7): %d, size of pointer (in bytes)\n', Info (7)) ; ++fprintf (' Info (8): %d, size of numerical entry (in bytes)\n', Info (8)) ; ++ ++fprintf ('\n Pivots with zero Markowitz cost removed to obtain submatrix S:\n') ; ++fprintf (' Info (57): %d, # of pivots with one entry in pivot column\n', Info (57)) ; ++fprintf (' Info (58): %d, # of pivots with one entry in pivot row\n', Info (58)) ; ++fprintf (' Info (59): %d, # of rows/columns in submatrix S (if square)\n', Info (59)) ; ++fprintf (' Info (60): %d ') ; ++if (Info (60) > 0) ++ fprintf ('submatrix S square and diagonal preserved\n') ; ++elseif (Info (60) == 0) ++ fprintf ('submatrix S not square or diagonal not preserved\n') ; ++else ++ fprintf ('\n') ; ++end ++fprintf (' Info (9): %d, # of "dense" rows in S\n', Info (9)) ; ++fprintf (' Info (10): %d, # of empty rows in S\n', Info (10)) ; ++fprintf (' Info (11): %d, # of "dense" columns in S\n', Info (11)) ; ++fprintf (' Info (12): %d, # of empty columns in S\n', Info (12)) ; ++fprintf (' Info (34): %g, symmetry of pattern of S\n', Info (34)) ; ++fprintf (' Info (35): %d, # of off-diagonal nonzeros in S+S''\n', Info (35)) ; ++fprintf (' Info (36): %d, nnz (diag (S))\n', Info (36)) ; ++ ++fprintf ('\n 2-by-2 pivoting to place large entries on diagonal:\n') ; ++fprintf (' Info (52): %d, # of small diagonal entries of S\n', Info (52)) ; ++fprintf (' Info (53): %d, # of unmatched small diagonal entries\n', Info (53)) ; ++fprintf (' Info (54): %g, symmetry of P2*S\n', Info (54)) ; ++fprintf (' Info (55): %d, # of off-diagonal entries in (P2*S)+(P2*S)''\n', Info (55)) ; ++fprintf (' Info (56): %d, nnz (diag (P2*S))\n', Info (56)) ; ++ ++fprintf ('\n AMD results, for strict diagonal pivoting:\n') ; ++fprintf (' Info (37): %d, est. nz in L and U\n', Info (37)) ; ++fprintf (' Info (38): %g, est. flop count\n', Info (38)) ; ++fprintf (' Info (39): %g, # of "dense" rows in S+S''\n', Info (39)) ; ++fprintf (' Info (40): %g, est. max. nz in any column of L\n', Info (40)) ; ++ ++fprintf ('\n Final strategy selection, based on the analysis above:\n') ; ++prstrat (' Info (19): %d, strategy used ', Info (19)) ; ++fprintf (' Info (20): %d, ordering used ', Info (20)) ; ++if (Info (20) == 0) ++ fprintf ('(COLAMD on A)\n') ; ++elseif (Info (20) == 1) ++ fprintf ('(AMD on A+A'')\n') ; ++elseif (Info (20) == 2) ++ fprintf ('(provided by user)\n') ; ++else ++ fprintf ('(undefined ordering option)\n') ; ++end ++fprintf (' Info (32): %d, Q fixed during numeric factorization: ', Info (32)) ; ++yes_no (Info (32)) ; ++fprintf (' Info (33): %d, prefer diagonal pivoting: ', Info (33)) ; ++yes_no (Info (33)) ; ++ ++fprintf ('\n symbolic analysis time and memory usage:\n') ; ++fprintf (' Info (13): %d, defragmentations during symbolic analysis\n', Info (13)) ; ++fprintf (' Info (14): %d, memory used during symbolic analysis (Units)\n', Info (14)) ; ++fprintf (' Info (15): %d, final size of symbolic factors (Units)\n', Info (15)) ; ++fprintf (' Info (16): %.2f, symbolic analysis CPU time (seconds)\n', Info (16)) ; ++fprintf (' Info (18): %.2f, symbolic analysis wall clock time (seconds)\n', Info (18)) ; ++ ++fprintf ('\n Estimates computed in the symbolic analysis:\n') ; ++fprintf (' Info (21): %d, est. size of LU factors (Units)\n', Info (21)) ; ++fprintf (' Info (22): %d, est. total peak memory usage (Units)\n', Info (22)) ; ++fprintf (' Info (23): %d, est. factorization flop count\n', Info (23)) ; ++fprintf (' Info (24): %d, est. nnz (L)\n', Info (24)) ; ++fprintf (' Info (25): %d, est. nnz (U)\n', Info (25)) ; ++fprintf (' Info (26): %d, est. initial size, variable-part of LU (Units)\n', Info (26)) ; ++fprintf (' Info (27): %d, est. peak size, of variable-part of LU (Units)\n', Info (27)) ; ++fprintf (' Info (28): %d, est. final size, of variable-part of LU (Units)\n', Info (28)) ; ++fprintf (' Info (29): %d, est. max frontal matrix size (# of entries)\n', Info (29)) ; ++fprintf (' Info (30): %d, est. max # of rows in frontal matrix\n', Info (30)) ; ++fprintf (' Info (31): %d, est. max # of columns in frontal matrix\n', Info (31)) ; ++ ++fprintf ('\n Computed in the numeric factorization (estimates shown above):\n') ; ++fprintf (' Info (41): %d, size of LU factors (Units)\n', Info (41)) ; ++fprintf (' Info (42): %d, total peak memory usage (Units)\n', Info (42)) ; ++fprintf (' Info (43): %d, factorization flop count\n', Info (43)) ; ++fprintf (' Info (44): %d, nnz (L)\n', Info (44)) ; ++fprintf (' Info (45): %d, nnz (U)\n', Info (45)) ; ++fprintf (' Info (46): %d, initial size of variable-part of LU (Units)\n', Info (46)) ; ++fprintf (' Info (47): %d, peak size of variable-part of LU (Units)\n', Info (47)) ; ++fprintf (' Info (48): %d, final size of variable-part of LU (Units)\n', Info (48)) ; ++fprintf (' Info (49): %d, max frontal matrix size (# of numerical entries)\n', Info (49)) ; ++fprintf (' Info (50): %d, max # of rows in frontal matrix\n', Info (50)) ; ++fprintf (' Info (51): %d, max # of columns in frontal matrix\n', Info (51)) ; ++ ++fprintf ('\n Computed in the numeric factorization (no estimates computed a priori):\n') ; ++fprintf (' Info (61): %d, defragmentations during numeric factorization\n', Info (61)) ; ++fprintf (' Info (62): %d, reallocations during numeric factorization\n', Info (62)) ; ++fprintf (' Info (63): %d, costly reallocations during numeric factorization\n', Info (63)) ; ++fprintf (' Info (64): %d, integer indices in compressed pattern of L and U\n', Info (64)) ; ++fprintf (' Info (65): %d, numerical values stored in L and U\n', Info (65)) ; ++fprintf (' Info (66): %.2f, numeric factorization CPU time (seconds)\n', Info (66)) ; ++fprintf (' Info (76): %.2f, numeric factorization wall clock time (seconds)\n', Info (76)) ; ++if (Info (66) > 0.05 & Info (43) > 0) ++fprintf (' mflops in numeric factorization phase: %.2f\n', 1e-6 * Info (43) / Info (66)) ; ++end ++fprintf (' Info (67): %d, nnz (diag (U))\n', Info (67)) ; ++fprintf (' Info (68): %g, reciprocal condition number estimate\n', Info (68)) ; ++fprintf (' Info (69): %g, matrix was ', Info (69)) ; ++if (Info (69) == 0) ++ fprintf ('not scaled\n') ; ++elseif (Info (69) == 2) ++ fprintf ('scaled (row max)\n') ; ++else ++ fprintf ('scaled (row sum)\n') ; ++end ++fprintf (' Info (70): %g, min. scale factor of rows of A\n', Info (70)) ; ++fprintf (' Info (71): %g, max. scale factor of rows of A\n', Info (71)) ; ++fprintf (' Info (72): %g, min. abs. on diagonal of U\n', Info (72)) ; ++fprintf (' Info (73): %g, max. abs. on diagonal of U\n', Info (73)) ; ++fprintf (' Info (74): %g, initial allocation parameter used\n', Info (74)) ; ++fprintf (' Info (75): %g, # of forced updates due to frontal growth\n', Info (75)) ; ++fprintf (' Info (77): %d, # of off-diaogonal pivots\n', Info (77)) ; ++fprintf (' Info (78): %d, nnz (L), if no small entries dropped\n', Info (78)) ; ++fprintf (' Info (79): %d, nnz (U), if no small entries dropped\n', Info (79)) ; ++fprintf (' Info (80): %d, # of small entries dropped\n', Info (80)) ; ++ ++fprintf ('\n Computed in the solve step:\n') ; ++fprintf (' Info (81): %d, iterative refinement steps taken\n', Info (81)) ; ++fprintf (' Info (82): %d, iterative refinement steps attempted\n', Info (82)) ; ++fprintf (' Info (83): %g, omega(1), sparse-backward error estimate\n', Info (83)) ; ++fprintf (' Info (84): %g, omega(2), sparse-backward error estimate\n', Info (84)) ; ++fprintf (' Info (85): %d, solve flop count\n', Info (85)) ; ++fprintf (' Info (86): %.2f, solve CPU time (seconds)\n', Info (86)) ; ++fprintf (' Info (87): %.2f, solve wall clock time (seconds)\n', Info (87)) ; ++ ++fprintf ('\n Info (88:90): unused\n\n') ; ++ ++%------------------------------------------------------------------------------- ++ ++function prstrat (fmt, strategy) ++fprintf (fmt, strategy) ; ++if (strategy == 1) ++ fprintf ('(unsymmetric)\n') ; ++ fprintf (' Q = COLAMD (A), Q refined during numerical\n') ; ++ fprintf (' factorization, and no attempt at diagonal pivoting.\n') ; ++elseif (strategy == 2) ++ fprintf ('(symmetric, with 2-by-2 pivoting)\n') ; ++ fprintf (' P2 = row permutation to place large values on the diagonal\n') ; ++ fprintf (' Q = AMD (P2*A+(P2*A)''), Q not refined during numeric factorization,\n') ; ++ fprintf (' and diagonal pivoting attempted.\n') ; ++elseif (strategy == 3) ++ fprintf ('(symmetric)\n') ; ++ fprintf (' Q = AMD (A+A''), Q not refined during numeric factorization,\n') ; ++ fprintf (' and diagonal pivoting (P=Q'') attempted.\n') ; ++else ++ strategy = 0 ; ++ fprintf ('(auto)\n') ; ++end ++ ++%------------------------------------------------------------------------------- ++ ++function yes_no (s) ++if (s == 0) ++ fprintf ('(no)\n') ; ++else ++ fprintf ('(yes)\n') ; ++end +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_simple.m UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_simple.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,61 @@ ++% umfpack_simple: a simple demo of UMFPACK ++% ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. ++% ++% UMFPACK License: ++% ++% Your use or distribution of UMFPACK or any modified version of ++% UMFPACK implies that you agree to this License. ++% ++% THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY ++% EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. ++% ++% Permission is hereby granted to use or copy this program, provided ++% that the Copyright, this License, and the Availability of the original ++% version is retained on all copies. User documentation of any code that ++% uses UMFPACK or any modified version of UMFPACK code must cite the ++% Copyright, this License, the Availability note, and "Used by permission." ++% Permission to modify the code and to distribute modified code is granted, ++% provided the Copyright, this License, and the Availability note are ++% retained, and a notice that the code was modified is included. This ++% software was developed with support from the National Science Foundation, ++% and is provided to you free of charge. ++% ++% Availability: http://www.cise.ufl.edu/research/sparse/umfpack ++% ++% See also: umfpack, umfpack_details ++ ++help umfpack_simple ++i = input ('Hit enter to agree to the above License: ', 's') ; ++if (~isempty (i)) ++ error ('terminating') ; ++end ++ ++format short ++ ++A = [ ++ 2 3 0 0 0 ++ 3 0 4 0 6 ++ 0 -1 -3 2 0 ++ 0 0 1 0 0 ++ 0 4 2 0 1 ++] ++ ++A = sparse (A) ; ++ ++b = [8 45 -3 3 19]' ++ ++fprintf ('Solution to Ax=b via UMFPACK:\n') ; ++fprintf ('x1 = umfpack (A, ''\\'', b)\n') ; ++ ++x1 = umfpack (A, '\\', b) ++ ++fprintf ('Solution to Ax=b via OCTAVE:\n') ; ++fprintf ('x2 = A\\b\n') ; ++ ++x2 = A\b ++ ++fprintf ('norm (x1-x2) should be small: %g\n', norm (x1-x2)) ; ++ ++fprintf ('Type ''umfpack_demo'' for a full demo of UMFPACK\n') ; +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_simple.m.out UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m.out +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_simple.m.out 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m.out 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,79 @@ ++octave:4> umfpack_simple ++umfpack_simple is the file: /home/dbateman/octave/devel/octave-sparse/UMFPACKv4.3/UMFPACK/OCTAVE/umfpack_simple.m ++ ++umfpack_simple: a simple demo of UMFPACK ++ ++UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++Davis. All Rights Reserved. ++ ++UMFPACK License: ++ ++ Your use or distribution of UMFPACK or any modified version of ++ UMFPACK implies that you agree to this License. ++ ++ THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY ++ EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. ++ ++ Permission is hereby granted to use or copy this program, provided ++ that the Copyright, this License, and the Availability of the original ++ version is retained on all copies. User documentation of any code that ++ uses UMFPACK or any modified version of UMFPACK code must cite the ++ Copyright, this License, the Availability note, and "Used by permission." ++ Permission to modify the code and to distribute modified code is granted, ++ provided the Copyright, this License, and the Availability note are ++ retained, and a notice that the code was modified is included. This ++ software was developed with support from the National Science Foundation, ++ and is provided to you free of charge. ++ ++Availability: http://www.cise.ufl.edu/research/sparse/umfpack ++ ++See also: umfpack, umfpack_details ++ ++ ++Additional help for built-in functions, operators, and variables ++is available in the on-line version of the manual. Use the command ++`help -i ' to search the manual index. ++ ++Help and information about Octave is also available on the WWW ++at http://www.octave.org and via the help@octave.org ++mailing list. ++Hit enter to agree to the above License: ++A = ++ ++ 2 3 0 0 0 ++ 3 0 4 0 6 ++ 0 -1 -3 2 0 ++ 0 0 1 0 0 ++ 0 4 2 0 1 ++ ++b = ++ ++ 8 ++ 45 ++ -3 ++ 3 ++ 19 ++ ++Solution to Ax=b via UMFPACK: ++x1 = umfpack (A, '\', b) ++x1 = ++ ++ 1.00000 ++ 2.00000 ++ 3.00000 ++ 4.00000 ++ 5.00000 ++ ++Solution to Ax=b via OCTAVE: ++x2 = A\b ++x2 = ++ ++ 1.00000 ++ 2.00000 ++ 3.00000 ++ 4.00000 ++ 5.00000 ++ ++norm (x1-x2) should be small: 0 ++Type 'umfpack_demo' for a full demo of UMFPACK ++octave:5> diary off +diff -uNr UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_solve.m UMFPACK/UMFPACK/OCTAVE/umfpack_solve.m +--- UMFPACKv4.4.orig/UMFPACK/OCTAVE/umfpack_solve.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/UMFPACK/OCTAVE/umfpack_solve.m 2004-12-30 01:58:46.000000000 +0100 +@@ -0,0 +1,97 @@ ++function x = umfpack_solve (arg1, op, arg2, Control) ++% UMFPACK_SOLVE ++% ++% x = umfpack_solve (A, '\', b, Control) ++% x = umfpack_solve (b, '/', A, Control) ++% ++% Computes x = A\b, or b/A, where A is square. Uses UMFPACK if A is sparse. ++% The Control argument is optional. ++% ++% See also umfpack, umfpack_make, umfpack_details, umfpack_report, ++% and umfpack_simple. ++ ++% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. ++% Davis. All Rights Reserved. Type umfpack_details for License. ++ ++%------------------------------------------------------------------------------- ++% check inputs and get default control parameters ++%------------------------------------------------------------------------------- ++ ++if (op == '\\') ++ A = arg1 ; ++ b = arg2 ; ++elseif (op == '/') ++ A = arg2 ; ++ b = arg1 ; ++else ++ help umfack_solve ++ error ('umfpack_solve: unrecognized operator') ; ++end ++ ++[m n] = size (A) ; ++if (m ~= n) ++ help umfpack_solve ++ error ('umfpack_solve: A must be square') ; ++end ++ ++[m1 n1] = size (b) ; ++if ((op == '\\' & n ~= m1) | (op == '/' & n1 ~= m)) ++ help umfpack_solve ++ error ('umfpack_solve: b has the wrong dimensions') ; ++end ++ ++if (nargin < 4) ++ Control = umfpack ; ++end ++ ++%------------------------------------------------------------------------------- ++% solve the system ++%------------------------------------------------------------------------------- ++ ++if (op == '\\') ++ ++ if (~issparse (A)) ++ ++ % A is not sparse, so just use MATLAB ++ x = A\b ; ++ ++ elseif (n1 == 1 & ~issparse (b)) ++ ++ % the UMFPACK '\' requires b to be a dense column vector ++ x = umfpack (A, '\\', b, Control) ; ++ ++ else ++ ++ % factorize with UMFPACK and do the forward/back solves in MATLAB ++ [L, U, P, Q, R] = umfpack (A, Control) ; ++ keyboard ++ x = Q * (U \ (L \ (P * (R \ b)))) ; ++ ++ end ++ ++else ++ ++ if (~issparse (A)) ++ ++ % A is not sparse, so just use MATLAB ++ x = b/A ; ++ ++ elseif (m1 == 1 & ~issparse (b)) ++ ++ % the UMFPACK '/' requires b to be a dense column vector ++ x = umfpack (b, '/', A, Control) ; ++ ++ else ++ ++ % factorize with UMFPACK and do the forward/back solves in MATLAB ++ % this mimics the behavior of x = b/A, except for the row scaling ++ [L, U, P, Q, R] = umfpack (A.', Control) ; ++ x = (Q * (U \ (L \ (P * (R \ (b.')))))).' ; ++ ++ % an alternative method: ++ % [L, U, P, Q, r] = umfpack (A, Control) ; ++ % x = (R \ (P' * (L.' \ (U.' \ (Q' * b.'))))).' ; ++ ++ end ++ ++end +diff -uNr UMFPACKv4.4.orig/AMD/OCTAVE/amd.cc UMFPACK/AMD/OCTAVE/amd.cc +--- UMFPACKv4.4.orig/AMD/OCTAVE/amd.cc 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/AMD/OCTAVE/amd.cc 2005-02-01 21:51:23.944874478 +0100 +@@ -0,0 +1,299 @@ ++/* ++ ++Copyright (C) 2004 David Bateman ++ ++This program is free software; you can redistribute it and/or modify it ++under the terms of the GNU General Public License as published by the ++Free Software Foundation; either version 2, or (at your option) any ++later version. ++ ++This program is distributed in the hope that it will be useful, but WITHOUT ++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; see the file COPYING. If not, write to the Free ++Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++In addition to the terms of the GPL, you are permitted to link ++this program with any Open Source program, as defined by the ++Open Source Initiative (www.opensource.org) ++ ++*/ ++ ++/* ++ ++This is the Octave interface to the UMFPACK AMD code, which bore the following ++copyright ++ ++ AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, ++ Patrick R. Amestoy, and Iain S. Duff. See ../README for License. ++ email: davis@cise.ufl.edu CISE Department, Univ. of Florida. ++ web: http://www.cise.ufl.edu/research/sparse/amd ++ -------------------------------------------------------------------------- ++ ++ Acknowledgements: This work was supported by the National Science ++ Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. ++ ++*/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ov-re-sparse.h" ++#include "ov-cx-sparse.h" ++ ++// External AMD functions in C ++extern "C" { ++#include "amd.h" ++} ++ ++DEFUN_DLD (amd, args, nargout, ++ "-*- texinfo -*-\n\ ++@deftypefn {Loadable Function} {@var{p} =} amd (@var{s})\n\ ++@deftypefnx {Loadable Function} {@var{Control} =} amd ()\n\ ++@deftypefnx {Loadable Function} {[@var{p}, @var{info}] =} amd (@var{s})\n\ ++\n\ ++AMD Approximate minimum degree permutation. Returns the approximate\n\ ++minimum degree permutation vector for the sparse matrix\n\ ++@code{@var{c} = @var{S} + @var{S}'}. The Cholesky factorization of\n\ ++@code{@var{c} (@var{p}, @var{p})}, or @code{@var{s} (@var{p}, @var{p})},\n\ ++tends to be sparser than that of @var{c} or @var{s}.\n\ ++@var{s} must be square. If @var{s} is full, @code{amd (@var{S})} is\n\ ++equivalent to @code{amd (sparse (@var{s}))}.\n\ ++\n\ ++@table @asis\n\ ++@item @var{Control} (1)\n\ ++If S is n-by-n, then rows/columns with more than\n\ ++@code{@dfn{max} (16, (@var{Control} (1)) * @dfn{sqrt} (@var{n}))} entries\n\ ++in @code{@var{s} + @var{S}'} are considered @emph{dense}, and ignored during\n\ ++ordering. They are placed last in the output permutation. The default is\n\ ++10.0 if @var{Control} is not present.\n\ ++@item @var{Control} (2)\n\ ++If nonzero, then aggressive absorption is performed. This is the default if\n\ ++@var{Control} is not present.\n\ ++@item @var{Control} (3)\n\ ++If nonzero, print statistics about the ordering.\n\ ++@end table\n\ ++\n\ ++@table @asis\n\ ++@item @var{Info} (1)\n\ ++status (0: ok, -1: out of memory, -2: matrix invalid)\n\ ++@item @var{Info} (2)\n\ ++@code{@var{n} = size (@var{a}, 1)}\n\ ++@item @var{Info} (3)\n\ ++@code{nnz (A)}\n\ ++@item @var{Info} (4)\n\ ++The symmetry of the matrix @var{s} (0.0 means purely unsymmetric, 1.0 means\n\ ++purely symmetric). Computed as: @code{@var{b} = tril (@var{s}, -1) +\n\ ++triu (@var{s}, 1); @var{symmetry} = nnz (@var{b} & @var{b}')\n\ ++/ nnz (@var{b});}\n\ ++@item @var{Info} (5)\n\ ++@code{nnz (diag (@var{s}))}\n\ ++@item @var{Info} (6)\n\ ++@dfn{nnz} in @code{@var{s} + @var{s}'}, excluding the diagonal\n\ ++(= @code{nnz (@var{b} + @var{b}')})\n\ ++@item @var{Info} (7)\n\ ++Number of @emph{dense} rows/columns in @code{@var{s} + @var{s}'}\n\ ++@item @var{Info} (8)\n\ ++The amount of memory used by AMD, in bytes\n\ ++@item @var{Info} (9)\n\ ++The number of memory compactions performed by AMD\n\ ++@end table\n\ ++\n\ ++The following statistics are slight upper bounds because of the\n\ ++approximate degree in AMD. The bounds are looser if @emph{dense}\n\ ++rows/columns are ignored during ordering @code{(@var{Info} (7) > 0)}.\n\ ++The statistics are for a subsequent factorization of the matrix\n\ ++@code{@var{c} (@var{p},@var{p})}. The LU factorization statistics assume\n \ ++no pivoting.\n\ ++\n\ ++@table @asis\n\ ++@item @var{Info} (10)\n\ ++The number of nonzeros in L, excluding the diagonal\n\ ++@item @var{Info} (11)\n\ ++The number of divide operations for LL', LDL', or LU\n\ ++@item @var{Info (12)}\n\ ++The number of multiply-subtract pairs for LL' or LDL'\n\ ++@item @var{Info} (13)\n\ ++The number of multiply-subtract pairs for LU\n\ ++@item @var{Info} (14)\n\ ++The max number of nonzeros in any column of L (incl. diagonal)\n\ ++@item @var{Info} (15:20)\n\ ++unused, reserved for future use\n\ ++@end table\n\ ++\n\ ++An assembly tree post-ordering is performed, which is typically the same\n\ ++as an elimination tree post-ordering. It is not always identical because\n\ ++of the approximate degree update used, and because @emph{dense} rows/columns\n\ ++do not take part in the post-order. It well-suited for a subsequent\n\ ++@dfn{chol}, however. If you require a precise elimination tree\n\ ++post-ordering, then do:\n\ ++\n\ ++@group\n\ ++ @var{p} = @dfn{amd} (@var{s});\n\ ++ % skip this if S already symmetric\n\ ++ @var{c} = spones (@var{s}) + spones (@var{s}');\n\ ++ [@var{ignore}, @var{q}] = sparsfun ('symetree', @var{c} (@var{p}, @var{p}));\n\ ++ @var{p} = @var{p} (@var{q});\n\ ++@end group\n\ ++\n\ ++AMD Version 1.1 (Jan. 21, 2004), Copyright @copyright{} 2004 by\n\ ++Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff.\n\ ++\n\ ++email: davis@@cise.ufl.edu (CISE Department, Univ. of Florida).\n\ ++\n\ ++web: http://www.cise.ufl.edu/research/sparse/amd\n\ ++\n\ ++Acknowledgements: This work was supported by the National Science\n\ ++Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270.\n\ ++@end deftypefn") ++{ ++ int nargin = args.length (); ++ octave_value_list retval; ++ int spumoni = 0; ++ ++ if (nargin > 2 || nargout > 2) ++ usage ("p = amd (A) or [p, Info] = amd (A, Control)"); ++ else if (nargin == 0) ++ { ++ // Get the default control parameter, and return ++ NDArray control (dim_vector (AMD_CONTROL, 1)); ++ double *control_ptr = control.fortran_vec (); ++ amd_defaults (control_ptr); ++ if (nargout == 0) ++ amd_control (control_ptr); ++ else ++ retval(0) = control; ++ } ++ else ++ { ++ NDArray control (dim_vector (AMD_CONTROL, 1)); ++ double *control_ptr = control.fortran_vec (); ++ amd_defaults (control_ptr); ++ ++ if (nargin > 1) ++ { ++ NDArray control_in = args(1).array_value(); ++ ++ if (error_state) ++ { ++ error ("amd: could not read control vector"); ++ return retval; ++ } ++ ++ dim_vector dv = control_in.dims (); ++ if (dv.length() > 2 || (dv(0) != 1 && dv(1) != 1)) ++ { ++ error ("amd: control vector isn't a vector"); ++ return retval; ++ } ++ ++ int nc = dv.numel (); ++ control (AMD_DENSE) = (nc > 0 ? control_in (AMD_DENSE) : ++ AMD_DEFAULT_DENSE); ++ control (AMD_AGGRESSIVE) = (nc > 1 ? control_in (AMD_AGGRESSIVE) : ++ AMD_DEFAULT_AGGRESSIVE); ++ spumoni = (nc > 2 ? (control_in (2) != 0) : 0); ++ } ++ ++ if (spumoni > 0) ++ amd_control (control_ptr); ++ ++ int *Ap, *Ai; ++ int n, m, nz; ++ ++ // These are here only so that the C++ destructors don't prematurally ++ // remove the underlying data we are interested in ++ SparseMatrix sm; ++ SparseComplexMatrix scm; ++ Matrix mm; ++ ComplexMatrix cm; ++ ++ if (args(0).class_name () != "sparse" && spumoni > 0) ++ octave_stdout << " input matrix A is full (sparse copy" ++ << " of A will be created)" << std::endl; ++ ++ if (args(0).is_complex_type ()) ++ { ++ scm = args(0).sparse_complex_matrix_value (); ++ Ai = scm.ridx (); ++ Ap = scm.cidx (); ++ m = scm.rows (); ++ n = scm.cols (); ++ nz = scm.nnz (); ++ } ++ else ++ { ++ sm = args(0).sparse_matrix_value (); ++ Ai = sm.ridx (); ++ Ap = sm.cidx (); ++ m = sm.rows (); ++ n = sm.cols (); ++ nz = sm.nnz (); ++ } ++ ++ if (spumoni > 0) ++ octave_stdout << " input matrix A is " << m << "-by-" << n ++ << std::endl; ++ ++ if (m != n) ++ { ++ error ("amd: A must be square"); ++ return retval; ++ } ++ ++ if (spumoni > 0) ++ octave_stdout << " input matrix A has " << nz << ++ " nonzero entries" << std::endl; ++ ++ // allocate workspace for output permutation ++ Array P(n+1); ++ int *P_ptr = P.fortran_vec (); ++ NDArray info (dim_vector (AMD_INFO, 1)); ++ double *info_ptr = info.fortran_vec (); ++ int result; ++ ++ // order the matrix ++ result = amd_order (n, Ap, Ai, P_ptr, control_ptr, info_ptr); ++ ++ // print results (including return value) ++ if (spumoni > 0) ++ amd_info (info_ptr); ++ ++ // check error conditions ++ if (result == AMD_OUT_OF_MEMORY) ++ error ("amd: out of memory"); ++ else if (result == AMD_INVALID) ++ error ("amd: input matrix A is corrupted"); ++ else ++ { ++ // copy the outputs to Octave ++ ++ // output permutation, P ++ NDArray perm (dim_vector (1, n)); ++ for (int i = 0; i < n; i++) ++ perm (i) = double (P(i) + 1); // 1-based indexing for Octave ++ ++ retval (0) = perm; ++ ++ // Info ++ if (nargout > 1) ++ retval (1) = info; ++ } ++ } ++ return retval; ++} ++ ++/* ++;;; Local Variables: *** ++;;; mode: C++ *** ++;;; End: *** ++*/ +diff -uNr UMFPACKv4.4.orig/AMD/OCTAVE/amd_demo.m UMFPACK/AMD/OCTAVE/amd_demo.m +--- UMFPACKv4.4.orig/AMD/OCTAVE/amd_demo.m 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/AMD/OCTAVE/amd_demo.m 2004-12-30 01:58:45.000000000 +0100 +@@ -0,0 +1,61 @@ ++function amd_demo ++% AMD DEMO ++% ++% A demo of AMD for OCTAVE. ++% ++% -------------------------------------------------------------------------- ++% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, ++% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. ++% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. ++% web: http://www.cise.ufl.edu/research/sparse/amd ++% -------------------------------------------------------------------------- ++% ++% See also: amd ++ ++% Get the Harwell/Boeing can_24 matrix. This is an example matrix from the ++% MATLAB-accessible UF sparse matrix collection, and can be loaded into ++% MATLAB with the statment "Problem = UFget ('HB/can_24')", after obtaining ++% the UFget function and its supporting routines at ++% http://www.cise.ufl.edu/sparse/mat . ++ ++load can_24.mat ++A = Problem.A ; ++n = size (A,1) ; ++ ++figure (1) ++clf ++hold off ++subplot (2,1,1) ; ++% remove the "_" from the name before printing it in the plot title ++title (sprintf ('%s', strrep (Problem.name, '_', '-'))) ; ++fprintf ('Matrix name: %s\n', Problem.name) ; ++fprintf ('Matrix title: %s\n', Problem.title) ; ++spy (A) ++ ++% print the details during AMD ordering and SYMBFACT ++control = amd (); ++control (3) = 1; ++ ++% order the matrix. Note that the Info argument is optional. ++fprintf ('\nIf the next step fails, then you have\n') ; ++fprintf ('not yet compiled the AMD mexFunction.\n') ; ++[p, Info] = amd (A, control) ; ++ ++% order again, but this time print some statistics ++[p, Info] = amd (A, [10 1 1]) ; ++ ++fprintf ('Permutation vector:\n') ; ++fprintf (' %2d', p) ; ++fprintf ('\n\n') ; ++ ++subplot (2,1,2) ; ++title ('Permuted matrix') ; ++spy (A (p,p)) ++ ++% approximations from amd: ++lnz2 = n + Info (10) ; ++fl2 = n + Info (11) + 2 * Info (12) ; ++fprintf ('\nResults from AMD''s approximate analysis:\n') ; ++fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz2) ; ++fprintf ('floating point operation count for chol (A (p,p)): %d\n\n', fl2) ; ++ +diff -uNr UMFPACKv4.4.orig/AMD/OCTAVE/amd_demo.m.out UMFPACK/AMD/OCTAVE/amd_demo.m.out +--- UMFPACKv4.4.orig/AMD/OCTAVE/amd_demo.m.out 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/AMD/OCTAVE/amd_demo.m.out 2004-12-30 01:58:45.000000000 +0100 +@@ -0,1 +1,21 @@ ++octave:3> amd_demo ++ans = 1 ++Matrix name: HB/can_24 ++Matrix title: 1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. ++ ++If the next step fails, then you have ++not yet compiled the AMD mexFunction. ++ input matrix A is 24-by-24 ++ input matrix A has 160 nonzero entries ++ input matrix A is 24-by-24 ++ input matrix A has 160 nonzero entries ++Permutation vector: ++ 23 21 11 24 13 6 17 9 15 5 16 8 2 10 14 18 1 3 4 7 12 19 22 20 ++ ++ ++Results from AMD's approximate analysis: ++number of nonzeros in L (including diagonal): 121 ++floating point operation count for chol (A (p,p)): 671 ++ ++octave:4> quit +--- UMFPACKv4.4.orig/AMD/OCTAVE/GNUmakefile 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/AMD/OCTAVE/GNUmakefile 2004-12-30 01:58:45.000000000 +0100 +@@ -0,0 +1,33 @@ ++#------------------------------------------------------------------------------ ++# GNUmakefile for the AMD MATLAB mexFunction ++#------------------------------------------------------------------------------ ++ ++all: amd ++ ++include ../Make/Make.include ++ ++MKOCT = mkoctfile -I../Include ++ ++OCT_SPARSE_INC = -I../../../ ++ ++AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ ++ amd_order amd_control amd_info amd_valid ++ ++INC = ../Include/amd.h ../Source/amd_internal.h ++ ++OCTAMD = $(addsuffix .o, $(subst amd_,amd_o_,$(AMD))) ++ ++amd_o_%.o: ../Source/amd_%.c $(INC) ++ $(MKOCT) -DDINT -c $< -o $@ ++ - $(MV) ../Source/amd_$*.o ++ ++# Note temporary addition of octave sparse path ++amd: amd.cc $(OCTAMD) $(INC) ++ $(MKOCT) amd.cc $(OCTAMD) $(OCT_SPARSE_INC) -o amd.oct ++ ++#------------------------------------------------------------------------------ ++# Remove all but the files in the original distribution ++#------------------------------------------------------------------------------ ++ ++purge: clean ++ - $(RM) amd.oct +diff -uNr UMFPACKv4.4.orig/AMD/OCTAVE/Makefile UMFPACK/AMD/OCTAVE/Makefile +--- UMFPACKv4.4.orig/AMD/OCTAVE/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ UMFPACK/AMD/OCTAVE/Makefile 2004-12-30 01:58:45.000000000 +0100 +@@ -0,0 +1,41 @@ ++#------------------------------------------------------------------------------ ++# compile the AMD mexFunction for MATLAB (original make only) ++#------------------------------------------------------------------------------ ++ ++# This is a very ugly Makefile, and is only provided for those who do not ++# have GNU make. Note that it is not used if you have GNU make. It ignores ++# dependency checking and just compiles everything. It was created ++# automatically, via make -n using the GNUmakefile. That way, I don't have ++# maintain two Makefiles. ++ ++all: amd ++ ++include ../Make/Make.include ++ ++MKOCT = mkoctfile -I../Include ++ ++OCT_SPARSE_INC = ../../../ ++ ++amd: ++ $(MKOCT) -DDINT -o amd_o_aat.o -c ../Source/amd_aat.c ++ $(MKOCT) -DDINT -o amd_o_1.o -c ../Source/amd_1.c ++ $(MKOCT) -DDINT -o amd_o_2.o -c ../Source/amd_2.c ++ $(MKOCT) -DDINT -o amd_o_dump.o -c ../Source/amd_dump.c ++ $(MKOCT) -DDINT -o amd_o_postorder.o -c ../Source/amd_postorder.c ++ $(MKOCT) -DDINT -o amd_o_post_tree.o -c ../Source/amd_post_tree.c ++ $(MKOCT) -DDINT -o amd_o_defaults.o -c ../Source/amd_defaults.c ++ $(MKOCT) -DDINT -o amd_o_order.o -c ../Source/amd_order.c ++ $(MKOCT) -DDINT -o amd_o_control.o -c ../Source/amd_control.c ++ $(MKOCT) -DDINT -o amd_o_info.o -c ../Source/amd_info.c ++ $(MKOCT) -DDINT -o amd_o_valid.o -c ../Source/amd_valid.c ++ $(MKOCT) -output amd.oct amd_mex.c amd_o_aat.o \ ++ amd_o_1.o amd_o_2.o amd_o_dump.o amd_o_postorder.o \ ++ amd_o_post_tree.o amd_o_defaults.o amd_o_order.o amd_o_control.o \ ++ amd_o_info.o amd_o_valid.o $(OCT_SPARSE_INC) -o amd.oct ++ ++#------------------------------------------------------------------------------ ++# Remove all but the files in the original distribution ++#------------------------------------------------------------------------------ ++ ++purge: clean ++ - $(RM) amd.oct +--- UMFPACKv4.4.orig/UMFPACK/Source/umf_solve.c 2005-01-17 17:21:29.000000000 +0100 ++++ UMFPACK/UMFPACK/Source/umf_solve.c 2005-02-02 00:01:22.904346651 +0100 +@@ -79,7 +79,8 @@ + double *Z2, *Y, *B2, *Rs ; + Int *Rperm, *Cperm, i, n, p, step, j, nz, status, p2, do_scale ; + #ifdef COMPLEX +- Int split ; ++ Int AXsplit ; ++ Int Bsplit ; + #endif + #ifndef NRECIPROCAL + Int do_recip = Numeric->do_recip ; +@@ -141,7 +142,7 @@ + return (UMFPACK_ERROR_argument_missing) ; + } + /* A, B, and X in split format if Az, Bz, and Xz present */ +- split = SPLIT (Az) && SPLIT (Bz) && SPLIT (Xz) ; ++ AXsplit = SPLIT (Az) || SPLIT(Xz); + Z = (Entry *) (SolveWork + 4*n) ; /* Entry Z [0..n-1] */ + S = (Entry *) (SolveWork + 6*n) ; /* Entry S [0..n-1] */ + Y = (double *) (SolveWork + 8*n) ; /* double Y [0..n-1] */ +@@ -150,10 +151,12 @@ + } + else + { +- /* A is ignored, only look at X and B for split/packed cases */ +- split = SPLIT (Bz) && SPLIT (Xz) ; ++ /* A is ignored, only look at X for split/packed cases */ ++ AXsplit = SPLIT(Xz); + } +- if (split) ++ Bsplit = SPLIT (Bz); ++ ++ if (AXsplit) + { + X = (Entry *) (SolveWork + 2*n) ; /* Entry X [0..n-1] */ + } +@@ -209,7 +212,7 @@ + for (p = 0 ; p < p2 ; p++) + { + /* Y [Ai [p]] += ABS (Ax [p]) ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + Y [Ai [p]] += d ; + } +@@ -219,7 +222,7 @@ + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ +- ASSIGN (bi, Bx, Bz, i, split) ; ++ ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + +@@ -276,7 +279,7 @@ + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + SCALE (X [i], Rs [i]) ; + } + } +@@ -286,7 +289,7 @@ + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + SCALE_DIV (X [i], Rs [i]) ; + } + } +@@ -302,7 +305,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Rperm [i]] ; */ +- ASSIGN (W [i], Bx, Bz, Rperm [i], split) ; ++ ASSIGN (W [i], Bx, Bz, Rperm [i], Bsplit) ; + } + } + } +@@ -311,7 +314,7 @@ + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ +- ASSIGN (Z [i], Bx, Bz, i, split) ; ++ ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) +@@ -321,7 +324,7 @@ + for (p = Ap [i] ; p < p2 ; p++) + { + /* Z [Ai [p]] -= Ax [p] * xi ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_SUB (Z [Ai [p]], aij, xi) ; + } + } +@@ -390,7 +393,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ +- ASSIGN (W [i], Bx, Bz, i, split) ; ++ ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + Z2 [i] = 0. ; + } + flops += (MULT_FLOPS + DECREMENT_FLOPS + ABS_FLOPS + 1) * nz ; +@@ -403,7 +406,7 @@ + i = Ai [p] ; + + /* axx = Ax [p] * xj ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT (axx, aij, xj) ; + + /* W [i] -= axx ; */ +@@ -493,7 +496,7 @@ + /* yi += ABS (Ax [p]) * Rs [Ai [p]] ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d * Rs [Ai [p]]) ; + } +@@ -513,7 +516,7 @@ + /* yi += ABS (Ax [p]) / Rs [Ai [p]] ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d / Rs [Ai [p]]) ; + } +@@ -534,7 +537,7 @@ + /* yi += ABS (Ax [p]) ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += d ; + } +@@ -546,7 +549,7 @@ + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ +- ASSIGN (bi, Bx, Bz, i, split) ; ++ ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + +@@ -568,7 +571,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Cperm [i]] ; */ +- ASSIGN (W [i], Bx, Bz, Cperm [i], split) ; ++ ASSIGN (W [i], Bx, Bz, Cperm [i], Bsplit) ; + } + } + else +@@ -577,7 +580,7 @@ + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ +- ASSIGN (Z [i], Bx, Bz, i, split) ; ++ ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) +@@ -587,7 +590,7 @@ + for (p = Ap [i] ; p < p2 ; p++) + { + /* zi -= conjugate (Ax [p]) * X [Ai [p]] ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, Bsplit) ; + MULT_SUB_CONJ (zi, X [Ai [p]], aij) ; + } + Z [i] = zi ; +@@ -696,13 +699,13 @@ + for (i = 0 ; i < n ; i++) + { + /* wi = B [i] ; */ +- ASSIGN (wi, Bx, Bz, i, split) ; ++ ASSIGN (wi, Bx, Bz, i, Bsplit) ; + z2i = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* axx = conjugate (Ax [p]) * X [Ai [p]] ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_CONJ (axx, X [Ai [p]], aij) ; + + /* wi -= axx ; */ +@@ -766,7 +769,7 @@ + /* yi += ABS (Ax [p]) * Rs [Ai [p]] ; */ + /* note that A.' is the array transpose, + * so no conjugate */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d * Rs [Ai [p]]) ; + } +@@ -786,7 +789,7 @@ + /* yi += ABS (Ax [p]) / Rs [Ai [p]] ; */ + /* note that A.' is the array transpose, + * so no conjugate */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d / Rs [Ai [p]]) ; + } +@@ -807,7 +810,7 @@ + /* yi += ABS (Ax [p]) */ + /* note that A.' is the array transpose, + * so no conjugate */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += d ; + } +@@ -819,7 +822,7 @@ + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ +- ASSIGN (bi, Bx, Bz, i, split) ; ++ ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + +@@ -841,7 +844,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Cperm [i]] ; */ +- ASSIGN (W [i], Bx, Bz, Cperm [i], split) ; ++ ASSIGN (W [i], Bx, Bz, Cperm [i], Bsplit) ; + } + } + else +@@ -850,7 +853,7 @@ + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ +- ASSIGN (Z [i], Bx, Bz, i, split) ; ++ ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) +@@ -860,7 +863,7 @@ + for (p = Ap [i] ; p < p2 ; p++) + { + /* zi -= Ax [p] * X [Ai [p]] ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_SUB (zi, aij, X [Ai [p]]) ; + } + Z [i] = zi ; +@@ -969,13 +972,13 @@ + for (i = 0 ; i < n ; i++) + { + /* wi = B [i] ; */ +- ASSIGN (wi, Bx, Bz, i, split) ; ++ ASSIGN (wi, Bx, Bz, i, Bsplit) ; + z2i = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* axx = Ax [p] * X [Ai [p]] ; */ +- ASSIGN (aij, Ax, Az, p, split) ; ++ ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT (axx, aij, X [Ai [p]]) ; + + /* wi -= axx ; */ +@@ -1011,7 +1014,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Rperm [i]] ; */ +- ASSIGN (X [i], Bx, Bz, Rperm [i], split) ; ++ ASSIGN (X [i], Bx, Bz, Rperm [i], Bsplit) ; + } + flops = UMF_lsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; +@@ -1027,7 +1030,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; +@@ -1043,7 +1046,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ +- ASSIGN (W [i], Bx, Bz, i, split) ; ++ ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lhsolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) +@@ -1063,7 +1066,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ +- ASSIGN (W [i], Bx, Bz, i, split) ; ++ ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_ltsolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) +@@ -1083,7 +1086,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lhsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; +@@ -1099,7 +1102,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_ltsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; +@@ -1115,7 +1118,7 @@ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ +- ASSIGN (W [i], Bx, Bz, i, split) ; ++ ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_usolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) +@@ -1134,7 +1137,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_usolve (Numeric, X, Pattern) ; + +@@ -1149,7 +1152,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Cperm [i]] ; */ +- ASSIGN (X [i], Bx, Bz, Cperm [i], split) ; ++ ASSIGN (X [i], Bx, Bz, Cperm [i], Bsplit) ; + } + flops = UMF_uhsolve (Numeric, X, Pattern) ; + +@@ -1164,7 +1167,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Cperm [i]] ; */ +- ASSIGN (X [i], Bx, Bz, Cperm [i], split) ; ++ ASSIGN (X [i], Bx, Bz, Cperm [i], Bsplit) ; + } + flops = UMF_utsolve (Numeric, X, Pattern) ; + +@@ -1179,7 +1182,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_uhsolve (Numeric, X, Pattern) ; + +@@ -1194,7 +1197,7 @@ + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ +- ASSIGN (X [i], Bx, Bz, i, split) ; ++ ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_utsolve (Numeric, X, Pattern) ; + +@@ -1206,7 +1209,7 @@ + + #ifdef COMPLEX + /* copy the solution back, from Entry X [ ] to double Xx [ ] and Xz [ ] */ +- if (split) ++ if (AXsplit) + { + for (i = 0 ; i < n ; i++) + { diff --git a/liboctave/UMFPACK.rules b/liboctave/UMFPACK.rules new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK.rules @@ -0,0 +1,183 @@ + +#---------------------------------------- +# integer-only routines (no real/complex): +#---------------------------------------- + +amd_o_%.o: $(srcdir)/UMFPACK/AMD/Source/amd_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT $< -o $@ + + +umf_o_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT $< -o $@ + +#---------------------------------------- +# Double precision, int version, for OCTAVE +#---------------------------------------- + +umf_od_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT $< -o $@ + +umf_od_%hsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%tsolve.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DCONJUGATE_SOLVE $< -o $@ + +umf_od_triplet_map_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DDO_MAP -DDO_VALUES $< -o $@ + +umf_od_triplet_map_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DDO_MAP $< -o $@ + +umf_od_triplet_nomap_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DDO_VALUES $< -o $@ + +umf_od_triplet_nomap_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT $< -o $@ + +umf_od_assemble_fixq.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_assemble.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DFIXQ $< -o $@ + +umf_od_store_lu_drop.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_store_lu.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DDROP $< -o $@ + +umfpack_od_wsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_solve.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT -DWSOLVE $< -o $@ + +umfpack_od_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDINT $< -o $@ + +#---------------------------------------- +# Complex double precision, int version, for OCTAVE +#---------------------------------------- + +umf_oz_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT $< -o $@ + +umf_oz_%hsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%tsolve.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DCONJUGATE_SOLVE $< -o $@ + +umf_oz_triplet_map_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DDO_MAP -DDO_VALUES $< -o $@ + +umf_oz_triplet_map_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DDO_MAP $< -o $@ + +umf_oz_triplet_nomap_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DDO_VALUES $< -o $@ + +umf_oz_triplet_nomap_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT $< -o $@ + +umf_oz_assemble_fixq.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_assemble.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DFIXQ $< -o $@ + +umf_oz_store_lu_drop.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_store_lu.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DDROP $< -o $@ + +umfpack_oz_wsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_solve.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT -DWSOLVE $< -o $@ + +umfpack_oz_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_%.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DZINT $< -o $@ + +#---------------------------------------- +# Generic routines for OCTAVE +#---------------------------------------- + +umfpack_o_timer.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_timer.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< -o $@ + +umfpack_o_tictoc.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_tictoc.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< -o $@ + +######################################################################## +# PIC rules +######################################################################## + +#---------------------------------------- +# integer-only routines (no real/complex): +#---------------------------------------- + +pic/amd_o_%.o: $(srcdir)/UMFPACK/AMD/Source/amd_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT $< -o $@ + + +pic/umf_o_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT $< -o $@ + +#---------------------------------------- +# Double precision, int version, for OCTAVE +#---------------------------------------- + +pic/umf_od_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT $< -o $@ + +pic/umf_od_%hsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%tsolve.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DCONJUGATE_SOLVE $< -o $@ + +pic/umf_od_triplet_map_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DDO_MAP -DDO_VALUES $< -o $@ + +pic/umf_od_triplet_map_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DDO_MAP $< -o $@ + +pic/umf_od_triplet_nomap_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DDO_VALUES $< -o $@ + +pic/umf_od_triplet_nomap_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT $< -o $@ + +pic/umf_od_assemble_fixq.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_assemble.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DFIXQ $< -o $@ + +pic/umf_od_store_lu_drop.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_store_lu.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DDROP $< -o $@ + +pic/umfpack_od_wsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_solve.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT -DWSOLVE $< -o $@ + +pic/umfpack_od_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DDINT $< -o $@ + +#---------------------------------------- +# Complex double precision, int version, for OCTAVE +#---------------------------------------- + +pic/umf_oz_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT $< -o $@ + +pic/umf_oz_%hsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_%tsolve.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DCONJUGATE_SOLVE $< -o $@ + +pic/umf_oz_triplet_map_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DDO_MAP -DDO_VALUES $< -o $@ + +pic/umf_oz_triplet_map_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DDO_MAP $< -o $@ + +pic/umf_oz_triplet_nomap_x.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DDO_VALUES $< -o $@ + +pic/umf_oz_triplet_nomap_nox.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_triplet.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT $< -o $@ + +pic/umf_oz_assemble_fixq.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_assemble.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DFIXQ $< -o $@ + +pic/umf_oz_store_lu_drop.o: $(srcdir)/UMFPACK/UMFPACK/Source/umf_store_lu.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DDROP $< -o $@ + +pic/umfpack_oz_wsolve.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_solve.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT -DWSOLVE $< -o $@ + +pic/umfpack_oz_%.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_%.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) -DZINT $< -o $@ + +#---------------------------------------- +# Generic routines for OCTAVE +#---------------------------------------- + +pic/umfpack_o_timer.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_timer.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) $< -o $@ + +pic/umfpack_o_tictoc.o: $(srcdir)/UMFPACK/UMFPACK/Source/umfpack_tictoc.c + $(CC) -c $(CPPFLAGS) $(CPICFLAG) $(ALL_CFLAGS) $< -o $@ + diff --git a/liboctave/UMFPACK/AMD/Demo/Makefile b/liboctave/UMFPACK/AMD/Demo/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/Makefile @@ -0,0 +1,79 @@ +#------------------------------------------------------------------------------ +# compile the AMD demo (for both GNU make or original make) +#----------------------------------------------------------------------------- + +all: amd_simple amd_demo amd_demo2 + +include ../Make/Make.include + +C = $(CC) $(CFLAGS) $(CONFIG) -I../Include + +INC = ../Include/amd.h + +../Lib/libamd.a: + ( cd ../Source ; make ) + +../Lib/libamdf77.a: + ( cd ../Source ; make fortran ) + +#------------------------------------------------------------------------------ +# Create the demo program, run it, and compare the output +#------------------------------------------------------------------------------ + +dist: + +amd_demo: amd_demo.c ../Lib/libamd.a $(INC) + $(C) -DDINT -o amd_demo amd_demo.c ../Lib/libamd.a $(LIB) + ./amd_demo > my_amd_demo.out + - diff amd_demo.out my_amd_demo.out + +amd_demo2: amd_demo2.c ../Lib/libamd.a $(INC) + $(C) -DDINT -o amd_demo2 amd_demo2.c ../Lib/libamd.a $(LIB) + ./amd_demo2 > my_amd_demo2.out + - diff amd_demo2.out my_amd_demo2.out + +amd_simple: amd_simple.c ../Lib/libamd.a $(INC) + $(C) -DDINT -o amd_simple amd_simple.c ../Lib/libamd.a $(LIB) + ./amd_simple > my_amd_simple.out + - diff amd_simple.out my_amd_simple.out + +#------------------------------------------------------------------------------ +# compile the Fortran demo +#------------------------------------------------------------------------------ + +fortran: amd_f77demo amd_f77simple + +cross: amd_f77cross + +amd_f77demo: amd_f77demo.f ../Lib/libamdf77.a + $(F77) $(F77FLAGS) -o amd_f77demo amd_f77demo.f ../Lib/libamdf77.a \ + $(F77LIB) + ./amd_f77demo > my_amd_f77demo.out + - diff amd_f77demo.out my_amd_f77demo.out + +amd_f77simple: amd_f77simple.f ../Lib/libamdf77.a + $(F77) $(F77FLAGS) -o amd_f77simple amd_f77simple.f \ + ../Lib/libamdf77.a $(F77LIB) + ./amd_f77simple > my_amd_f77simple.out + - diff amd_f77simple.out my_amd_f77simple.out + +amd_f77wrapper.o: amd_f77wrapper.c + $(C) -DDINT -c amd_f77wrapper.c + +amd_f77cross: amd_f77cross.f amd_f77wrapper.o ../Lib/libamd.a + $(F77) $(F77FLAGS) -o amd_f77cross amd_f77cross.f amd_f77wrapper.o \ + ../Lib/libamd.a $(F77LIB) + ./amd_f77cross > my_amd_f77cross.out + - diff amd_f77cross.out my_amd_f77cross.out + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) amd_demo my_amd_demo.out + - $(RM) amd_demo2 my_amd_demo2.out + - $(RM) amd_simple my_amd_simple.out + - $(RM) amd_f77demo my_amd_f77demo.out + - $(RM) amd_f77simple my_amd_f77simple.out + - $(RM) amd_f77cross my_amd_f77cross.out diff --git a/liboctave/UMFPACK/AMD/Demo/amd_demo.c b/liboctave/UMFPACK/AMD/Demo/amd_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_demo.c @@ -0,0 +1,169 @@ +/* ========================================================================= */ +/* === AMD demo main program =============================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* A simple C main program that illustrates the use of the ANSI C interface + * to AMD. + */ + +#include "amd.h" +#include +#include + +int main (int argc, char **argv) +{ + /* The symmetric can_24 Harwell/Boeing matrix, including upper and lower + * triangular parts, and the diagonal entries. Note that this matrix is + * 0-based, with row and column indices in the range 0 to n-1. */ + int n = 24, nz, + Ap [ ] = { 0, 9, 15, 21, 27, 33, 39, 48, 57, 61, 70, 76, 82, 88, 94, 100, + 106, 110, 119, 128, 137, 143, 152, 156, 160 }, + Ai [ ] = { + /* column 0: */ 0, 5, 6, 12, 13, 17, 18, 19, 21, + /* column 1: */ 1, 8, 9, 13, 14, 17, + /* column 2: */ 2, 6, 11, 20, 21, 22, + /* column 3: */ 3, 7, 10, 15, 18, 19, + /* column 4: */ 4, 7, 9, 14, 15, 16, + /* column 5: */ 0, 5, 6, 12, 13, 17, + /* column 6: */ 0, 2, 5, 6, 11, 12, 19, 21, 23, + /* column 7: */ 3, 4, 7, 9, 14, 15, 16, 17, 18, + /* column 8: */ 1, 8, 9, 14, + /* column 9: */ 1, 4, 7, 8, 9, 13, 14, 17, 18, + /* column 10: */ 3, 10, 18, 19, 20, 21, + /* column 11: */ 2, 6, 11, 12, 21, 23, + /* column 12: */ 0, 5, 6, 11, 12, 23, + /* column 13: */ 0, 1, 5, 9, 13, 17, + /* column 14: */ 1, 4, 7, 8, 9, 14, + /* column 15: */ 3, 4, 7, 15, 16, 18, + /* column 16: */ 4, 7, 15, 16, + /* column 17: */ 0, 1, 5, 7, 9, 13, 17, 18, 19, + /* column 18: */ 0, 3, 7, 9, 10, 15, 17, 18, 19, + /* column 19: */ 0, 3, 6, 10, 17, 18, 19, 20, 21, + /* column 20: */ 2, 10, 19, 20, 21, 22, + /* column 21: */ 0, 2, 6, 10, 11, 19, 20, 21, 22, + /* column 22: */ 2, 20, 21, 22, + /* column 23: */ 6, 11, 12, 23 } ; + + int P [24], Pinv [24], i, j, k, jnew, p, inew, result ; + double Control [AMD_CONTROL], Info [AMD_INFO] ; + char A [24][24] ; + + printf ("AMD demo, with the 24-by-24 Harwell/Boeing matrix, can_24:\n") ; + + /* get the default parameters, and print them */ + amd_defaults (Control) ; + amd_control (Control) ; + + /* print the input matrix */ + nz = Ap [n] ; + printf ("\nInput matrix: %d-by-%d, with %d entries.\n" + " Note that for a symmetric matrix such as this one, only the\n" + " strictly lower or upper triangular parts would need to be\n" + " passed to AMD, since AMD computes the ordering of A+A'. The\n" + " diagonal entries are also not needed, since AMD ignores them.\n" + , n, n, nz) ; + for (j = 0 ; j < n ; j++) + { + printf ("\nColumn: %d, number of entries: %d, with row indices in" + " Ai [%d ... %d]:\n row indices:", + j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + printf (" %d", i) ; + } + printf ("\n") ; + } + + /* print a character plot of the input matrix. This is only reasonable + * because the matrix is small. */ + printf ("\nPlot of input matrix pattern:\n") ; + for (j = 0 ; j < n ; j++) + { + for (i = 0 ; i < n ; i++) A [i][j] = '.' ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + A [i][j] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf ("\n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf ("\n") ; + } + + /* order the matrix */ + result = amd_order (n, Ap, Ai, P, Control, Info) ; + printf ("return value from amd_order: %d (should be %d)\n", + result, AMD_OK) ; + + /* print the statistics */ + amd_info (Info) ; + + if (result != AMD_OK) + { + printf ("AMD failed\n") ; + exit (1) ; + } + + /* print the permutation vector, P, and compute the inverse permutation */ + printf ("Permutation vector:\n") ; + for (k = 0 ; k < n ; k++) + { + /* row/column j is the kth row/column in the permuted matrix */ + j = P [k] ; + Pinv [j] = k ; + printf (" %2d", j) ; + } + printf ("\n\n") ; + + printf ("Inverse permutation vector:\n") ; + for (j = 0 ; j < n ; j++) + { + k = Pinv [j] ; + printf (" %2d", k) ; + } + printf ("\n\n") ; + + /* print a character plot of the permuted matrix. */ + printf ("\nPlot of permuted matrix pattern:\n") ; + for (jnew = 0 ; jnew < n ; jnew++) + { + j = P [jnew] ; + for (inew = 0 ; inew < n ; inew++) A [inew][jnew] = '.' ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + inew = Pinv [Ai [p]] ; + A [inew][jnew] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf ("\n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf ("\n") ; + } + + return (0) ; +} diff --git a/liboctave/UMFPACK/AMD/Demo/amd_demo.out b/liboctave/UMFPACK/AMD/Demo/amd_demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_demo.out @@ -0,0 +1,177 @@ +AMD demo, with the 24-by-24 Harwell/Boeing matrix, can_24: + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + + +Input matrix: 24-by-24, with 160 entries. + Note that for a symmetric matrix such as this one, only the + strictly lower or upper triangular parts would need to be + passed to AMD, since AMD computes the ordering of A+A'. The + diagonal entries are also not needed, since AMD ignores them. + +Column: 0, number of entries: 9, with row indices in Ai [0 ... 8]: + row indices: 0 5 6 12 13 17 18 19 21 + +Column: 1, number of entries: 6, with row indices in Ai [9 ... 14]: + row indices: 1 8 9 13 14 17 + +Column: 2, number of entries: 6, with row indices in Ai [15 ... 20]: + row indices: 2 6 11 20 21 22 + +Column: 3, number of entries: 6, with row indices in Ai [21 ... 26]: + row indices: 3 7 10 15 18 19 + +Column: 4, number of entries: 6, with row indices in Ai [27 ... 32]: + row indices: 4 7 9 14 15 16 + +Column: 5, number of entries: 6, with row indices in Ai [33 ... 38]: + row indices: 0 5 6 12 13 17 + +Column: 6, number of entries: 9, with row indices in Ai [39 ... 47]: + row indices: 0 2 5 6 11 12 19 21 23 + +Column: 7, number of entries: 9, with row indices in Ai [48 ... 56]: + row indices: 3 4 7 9 14 15 16 17 18 + +Column: 8, number of entries: 4, with row indices in Ai [57 ... 60]: + row indices: 1 8 9 14 + +Column: 9, number of entries: 9, with row indices in Ai [61 ... 69]: + row indices: 1 4 7 8 9 13 14 17 18 + +Column: 10, number of entries: 6, with row indices in Ai [70 ... 75]: + row indices: 3 10 18 19 20 21 + +Column: 11, number of entries: 6, with row indices in Ai [76 ... 81]: + row indices: 2 6 11 12 21 23 + +Column: 12, number of entries: 6, with row indices in Ai [82 ... 87]: + row indices: 0 5 6 11 12 23 + +Column: 13, number of entries: 6, with row indices in Ai [88 ... 93]: + row indices: 0 1 5 9 13 17 + +Column: 14, number of entries: 6, with row indices in Ai [94 ... 99]: + row indices: 1 4 7 8 9 14 + +Column: 15, number of entries: 6, with row indices in Ai [100 ... 105]: + row indices: 3 4 7 15 16 18 + +Column: 16, number of entries: 4, with row indices in Ai [106 ... 109]: + row indices: 4 7 15 16 + +Column: 17, number of entries: 9, with row indices in Ai [110 ... 118]: + row indices: 0 1 5 7 9 13 17 18 19 + +Column: 18, number of entries: 9, with row indices in Ai [119 ... 127]: + row indices: 0 3 7 9 10 15 17 18 19 + +Column: 19, number of entries: 9, with row indices in Ai [128 ... 136]: + row indices: 0 3 6 10 17 18 19 20 21 + +Column: 20, number of entries: 6, with row indices in Ai [137 ... 142]: + row indices: 2 10 19 20 21 22 + +Column: 21, number of entries: 9, with row indices in Ai [143 ... 151]: + row indices: 0 2 6 10 11 19 20 21 22 + +Column: 22, number of entries: 4, with row indices in Ai [152 ... 155]: + row indices: 2 20 21 22 + +Column: 23, number of entries: 4, with row indices in Ai [156 ... 159]: + row indices: 6 11 12 23 + +Plot of input matrix pattern: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X . . . . X X . . . . . X X . . . X X X . X . . + 1: . X . . . . . . X X . . . X X . . X . . . . . . + 2: . . X . . . X . . . . X . . . . . . . . X X X . + 3: . . . X . . . X . . X . . . . X . . X X . . . . + 4: . . . . X . . X . X . . . . X X X . . . . . . . + 5: X . . . . X X . . . . . X X . . . X . . . . . . + 6: X . X . . X X . . . . X X . . . . . . X . X . X + 7: . . . X X . . X . X . . . . X X X X X . . . . . + 8: . X . . . . . . X X . . . . X . . . . . . . . . + 9: . X . . X . . X X X . . . X X . . X X . . . . . +10: . . . X . . . . . . X . . . . . . . X X X X . . +11: . . X . . . X . . . . X X . . . . . . . . X . X +12: X . . . . X X . . . . X X . . . . . . . . . . X +13: X X . . . X . . . X . . . X . . . X . . . . . . +14: . X . . X . . X X X . . . . X . . . . . . . . . +15: . . . X X . . X . . . . . . . X X . X . . . . . +16: . . . . X . . X . . . . . . . X X . . . . . . . +17: X X . . . X . X . X . . . X . . . X X X . . . . +18: X . . X . . . X . X X . . . . X . X X X . . . . +19: X . . X . . X . . . X . . . . . . X X X X X . . +20: . . X . . . . . . . X . . . . . . . . X X X X . +21: X . X . . . X . . . X X . . . . . . . X X X X . +22: . . X . . . . . . . . . . . . . . . . . X X X . +23: . . . . . . X . . . . X X . . . . . . . . . . X +return value from amd_order: 0 (should be 0) + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 24 + nz, number of nonzeros in A: 160 + symmetry of A: 1.0000 + number of nonzeros on diagonal: 24 + nonzeros in pattern of A+A' (excl. diagonal): 136 + # dense rows/columns of A+A': 0 + memory used, in bytes: 1516 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 97 + nonzeros in L (including diagonal): 121 + # divide operations for LDL' or LU: 97 + # multiply-subtract operations for LDL': 275 + # multiply-subtract operations for LU: 453 + max nz. in any column of L (incl. diagonal): 8 + + chol flop count for real A, sqrt counted as 1 flop: 671 + LDL' flop count for real A: 647 + LDL' flop count for complex A: 3073 + LU flop count for real A (with no pivoting): 1003 + LU flop count for complex A (with no pivoting): 4497 + +Permutation vector: + 22 20 10 23 12 5 16 8 14 4 15 7 1 9 13 17 0 2 3 6 11 18 21 19 + +Inverse permutation vector: + 16 12 17 18 9 5 19 11 7 13 2 20 4 14 8 10 6 15 21 23 1 22 0 3 + + +Plot of permuted matrix pattern: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X X . . . . . . . . . . . . . . . X . . . . X . + 1: X X X . . . . . . . . . . . . . . X . . . . X X + 2: . X X . . . . . . . . . . . . . . . X . . X X X + 3: . . . X X . . . . . . . . . . . . . . X X . . . + 4: . . . X X X . . . . . . . . . . X . . X X . . . + 5: . . . . X X . . . . . . . . X X X . . X . . . . + 6: . . . . . . X . . X X X . . . . . . . . . . . . + 7: . . . . . . . X X . . . X X . . . . . . . . . . + 8: . . . . . . . X X X . X X X . . . . . . . . . . + 9: . . . . . . X . X X X X . X . . . . . . . . . . +10: . . . . . . X . . X X X . . . . . . X . . X . . +11: . . . . . . X . X X X X . X . X . . X . . X . . +12: . . . . . . . X X . . . X X X X . . . . . . . . +13: . . . . . . . X X X . X X X X X . . . . . X . . +14: . . . . . X . . . . . . X X X X X . . . . . . . +15: . . . . . X . . . . . X X X X X X . . . . X . X +16: . . . . X X . . . . . . . . X X X . . X . X X X +17: X X . . . . . . . . . . . . . . . X . X X . X . +18: . . X . . . . . . . X X . . . . . . X . . X . X +19: . . . X X X . . . . . . . . . . X X . X X . X X +20: . . . X X . . . . . . . . . . . . X . X X . X . +21: . . X . . . . . . . X X . X . X X . X . . X . X +22: X X X . . . . . . . . . . . . . X X . X X . X X +23: . X X . . . . . . . . . . . . X X . X X . X X X diff --git a/liboctave/UMFPACK/AMD/Demo/amd_demo2.c b/liboctave/UMFPACK/AMD/Demo/amd_demo2.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_demo2.c @@ -0,0 +1,261 @@ +/* ========================================================================= */ +/* === AMD demo main program (jumbled matrix version) ====================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* A simple C main program that illustrates the use of the ANSI C interface + * to AMD. + * + * Identical to amd_demo.c, except that it operates on an input matrix that has + * unsorted columns and duplicate entries. + */ + +#include "amd.h" +#include +#include + +int main (int argc, char **argv) +{ + /* The symmetric can_24 Harwell/Boeing matrix (jumbled, and not symmetric). + * Since AMD operates on A+A', only A(i,j) or A(j,i) need to be specified, + * or both. The diagonal entries are optional (some are missing). + * There are many duplicate entries, which must be removed. */ + int n = 24, nz, + Ap [ ] = { 0, 9, 14, 20, 28, 33, 37, 44, 53, 58, 63, 63, 66, 69, 72, 75, + 78, 82, 86, 91, 97, 101, 112, 112, 116 }, + Ai [ ] = { + /* column 0: */ 0, 17, 18, 21, 5, 12, 5, 0, 13, + /* column 1: */ 14, 1, 8, 13, 17, + /* column 2: */ 2, 20, 11, 6, 11, 22, + /* column 3: */ 3, 3, 10, 7, 18, 18, 15, 19, + /* column 4: */ 7, 9, 15, 14, 16, + /* column 5: */ 5, 13, 6, 17, + /* column 6: */ 5, 0, 11, 6, 12, 6, 23, + /* column 7: */ 3, 4, 9, 7, 14, 16, 15, 17, 18, + /* column 8: */ 1, 9, 14, 14, 14, + /* column 9: */ 7, 13, 8, 1, 17, + /* column 10: */ + /* column 11: */ 2, 12, 23, + /* column 12: */ 5, 11, 12, + /* column 13: */ 0, 13, 17, + /* column 14: */ 1, 9, 14, + /* column 15: */ 3, 15, 16, + /* column 16: */ 16, 4, 4, 15, + /* column 17: */ 13, 17, 19, 17, + /* column 18: */ 15, 17, 19, 9, 10, + /* column 19: */ 17, 19, 20, 0, 6, 10, + /* column 20: */ 22, 10, 20, 21, + /* column 21: */ 6, 2, 10, 19, 20, 11, 21, 22, 22, 22, 22, + /* column 22: */ + /* column 23: */ 12, 11, 12, 23 } ; + + int Rp [25], Ri [116] ; + int P [24], Pinv [24], i, j, k, jnew, p, inew, result ; + double Control [AMD_CONTROL], Info [AMD_INFO] ; + char A [24][24] ; + + printf ("AMD demo, with a jumbled version of the 24-by-24\n") ; + printf ("Harwell/Boeing matrix, can_24:\n") ; + + /* get the default parameters, and print them */ + amd_defaults (Control) ; + amd_control (Control) ; + + /* print the input matrix */ + nz = Ap [n] ; + printf ("\nJumbled input matrix: %d-by-%d, with %d entries.\n" + " Note that for a symmetric matrix such as this one, only the\n" + " strictly lower or upper triangular parts would need to be\n" + " passed to AMD, since AMD computes the ordering of A+A'. The\n" + " diagonal entries are also not needed, since AMD ignores them.\n" + " This version of the matrix has jumbled columns and duplicate\n" + " row indices, and must be fixed by amd_preprocess prior to\n" + " ordering it with amd_order.\n" , n, n, nz) ; + for (j = 0 ; j < n ; j++) + { + printf ("\nColumn: %d, number of entries: %d, with row indices in" + " Ai [%d ... %d]:\n row indices:", + j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + printf (" %d", i) ; + } + printf ("\n") ; + } + + /* print a character plot of the input matrix. This is only reasonable + * because the matrix is small. */ + printf ("\nPlot of (jumbled) input matrix pattern:\n") ; + for (j = 0 ; j < n ; j++) + { + for (i = 0 ; i < n ; i++) A [i][j] = '.' ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + A [i][j] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf ("\n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf ("\n") ; + } + + /* sort, remove duplicates, and transpose A to get R */ + result = amd_preprocess (n, Ap, Ai, Rp, Ri) ; + printf ("return value from amd_preprocess: %d (should be %d)\n", + result, AMD_OK) ; + + if (result != AMD_OK) + { + printf ("AMD failed\n") ; + exit (1) ; + } + + /* print the sorted/transposed matrix R */ + printf ("\nThe column-oriented form of the sorted/transposed matrix R:\n"); + for (j = 0 ; j < n ; j++) + { + printf ("\nColumn: %d, number of entries: %d, with row indices in" + " Ri [%d ... %d]:\n row indices:", + j, Rp [j+1] - Rp [j], Rp [j], Rp [j+1]-1) ; + for (p = Rp [j] ; p < Rp [j+1] ; p++) + { + i = Ri [p] ; + printf (" %d", i) ; + } + printf ("\n") ; + } + + /* print a character plot of the matrix R. */ + printf ("\nPlot of the sorted/transposed matrix R:\n") ; + for (j = 0 ; j < n ; j++) + { + for (i = 0 ; i < n ; i++) A [i][j] = '.' ; + for (p = Rp [j] ; p < Rp [j+1] ; p++) + { + i = Ri [p] ; + A [i][j] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf (" \n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf (" \n") ; + } + + /* print a character plot of the matrix R+R'. */ + printf ("\nPlot of symmetric matrix to be ordered by amd_order:\n") ; + for (j = 0 ; j < n ; j++) + { + for (i = 0 ; i < n ; i++) A [i][j] = '.' ; + } + for (j = 0 ; j < n ; j++) + { + A [j][j] = 'X' ; + for (p = Rp [j] ; p < Rp [j+1] ; p++) + { + i = Ri [p] ; + A [i][j] = 'X' ; + A [j][i] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf ("\n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf ("\n") ; + } + + /* order the matrix */ + result = amd_order (n, Rp, Ri, P, Control, Info) ; + printf ("return value from amd_order: %d (should be %d)\n", + result, AMD_OK) ; + + /* print the statistics */ + amd_info (Info) ; + + if (result != AMD_OK) + { + printf ("AMD failed\n") ; + exit (1) ; + } + + /* print the permutation vector, P, and compute the inverse permutation */ + printf ("Permutation vector:\n") ; + for (k = 0 ; k < n ; k++) + { + /* row/column j is the kth row/column in the permuted matrix */ + j = P [k] ; + Pinv [j] = k ; + printf (" %2d", j) ; + } + printf ("\n\n") ; + + printf ("Inverse permutation vector:\n") ; + for (j = 0 ; j < n ; j++) + { + k = Pinv [j] ; + printf (" %2d", k) ; + } + printf ("\n\n") ; + + /* print a character plot of the permuted matrix. */ + printf ("\nPlot of (symmetrized) permuted matrix pattern:\n") ; + for (j = 0 ; j < n ; j++) + { + for (i = 0 ; i < n ; i++) A [i][j] = '.' ; + } + for (jnew = 0 ; jnew < n ; jnew++) + { + j = P [jnew] ; + A [jnew][jnew] = 'X' ; + for (p = Rp [j] ; p < Rp [j+1] ; p++) + { + inew = Pinv [Ri [p]] ; + A [inew][jnew] = 'X' ; + A [jnew][inew] = 'X' ; + } + } + printf (" ") ; + for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; + printf ("\n") ; + for (i = 0 ; i < n ; i++) + { + printf ("%2d: ", i) ; + for (j = 0 ; j < n ; j++) + { + printf (" %c", A [i][j]) ; + } + printf ("\n") ; + } + + return (0) ; +} diff --git a/liboctave/UMFPACK/AMD/Demo/amd_demo2.out b/liboctave/UMFPACK/AMD/Demo/amd_demo2.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_demo2.out @@ -0,0 +1,310 @@ +AMD demo, with a jumbled version of the 24-by-24 +Harwell/Boeing matrix, can_24: + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + + +Jumbled input matrix: 24-by-24, with 116 entries. + Note that for a symmetric matrix such as this one, only the + strictly lower or upper triangular parts would need to be + passed to AMD, since AMD computes the ordering of A+A'. The + diagonal entries are also not needed, since AMD ignores them. + This version of the matrix has jumbled columns and duplicate + row indices, and must be fixed by amd_preprocess prior to + ordering it with amd_order. + +Column: 0, number of entries: 9, with row indices in Ai [0 ... 8]: + row indices: 0 17 18 21 5 12 5 0 13 + +Column: 1, number of entries: 5, with row indices in Ai [9 ... 13]: + row indices: 14 1 8 13 17 + +Column: 2, number of entries: 6, with row indices in Ai [14 ... 19]: + row indices: 2 20 11 6 11 22 + +Column: 3, number of entries: 8, with row indices in Ai [20 ... 27]: + row indices: 3 3 10 7 18 18 15 19 + +Column: 4, number of entries: 5, with row indices in Ai [28 ... 32]: + row indices: 7 9 15 14 16 + +Column: 5, number of entries: 4, with row indices in Ai [33 ... 36]: + row indices: 5 13 6 17 + +Column: 6, number of entries: 7, with row indices in Ai [37 ... 43]: + row indices: 5 0 11 6 12 6 23 + +Column: 7, number of entries: 9, with row indices in Ai [44 ... 52]: + row indices: 3 4 9 7 14 16 15 17 18 + +Column: 8, number of entries: 5, with row indices in Ai [53 ... 57]: + row indices: 1 9 14 14 14 + +Column: 9, number of entries: 5, with row indices in Ai [58 ... 62]: + row indices: 7 13 8 1 17 + +Column: 10, number of entries: 0, with row indices in Ai [63 ... 62]: + row indices: + +Column: 11, number of entries: 3, with row indices in Ai [63 ... 65]: + row indices: 2 12 23 + +Column: 12, number of entries: 3, with row indices in Ai [66 ... 68]: + row indices: 5 11 12 + +Column: 13, number of entries: 3, with row indices in Ai [69 ... 71]: + row indices: 0 13 17 + +Column: 14, number of entries: 3, with row indices in Ai [72 ... 74]: + row indices: 1 9 14 + +Column: 15, number of entries: 3, with row indices in Ai [75 ... 77]: + row indices: 3 15 16 + +Column: 16, number of entries: 4, with row indices in Ai [78 ... 81]: + row indices: 16 4 4 15 + +Column: 17, number of entries: 4, with row indices in Ai [82 ... 85]: + row indices: 13 17 19 17 + +Column: 18, number of entries: 5, with row indices in Ai [86 ... 90]: + row indices: 15 17 19 9 10 + +Column: 19, number of entries: 6, with row indices in Ai [91 ... 96]: + row indices: 17 19 20 0 6 10 + +Column: 20, number of entries: 4, with row indices in Ai [97 ... 100]: + row indices: 22 10 20 21 + +Column: 21, number of entries: 11, with row indices in Ai [101 ... 111]: + row indices: 6 2 10 19 20 11 21 22 22 22 22 + +Column: 22, number of entries: 0, with row indices in Ai [112 ... 111]: + row indices: + +Column: 23, number of entries: 4, with row indices in Ai [112 ... 115]: + row indices: 12 11 12 23 + +Plot of (jumbled) input matrix pattern: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X . . . . . X . . . . . . X . . . . . X . . . . + 1: . X . . . . . . X X . . . . X . . . . . . . . . + 2: . . X . . . . . . . . X . . . . . . . . . X . . + 3: . . . X . . . X . . . . . . . X . . . . . . . . + 4: . . . . . . . X . . . . . . . . X . . . . . . . + 5: X . . . . X X . . . . . X . . . . . . . . . . . + 6: . . X . . X X . . . . . . . . . . . . X . X . . + 7: . . . X X . . X . X . . . . . . . . . . . . . . + 8: . X . . . . . . . X . . . . . . . . . . . . . . + 9: . . . . X . . X X . . . . . X . . . X . . . . . +10: . . . X . . . . . . . . . . . . . . X X X X . . +11: . . X . . . X . . . . . X . . . . . . . . X . X +12: X . . . . . X . . . . X X . . . . . . . . . . X +13: X X . . . X . . . X . . . X . . . X . . . . . . +14: . X . . X . . X X . . . . . X . . . . . . . . . +15: . . . X X . . X . . . . . . . X X . X . . . . . +16: . . . . X . . X . . . . . . . X X . . . . . . . +17: X X . . . X . X . X . . . X . . . X X X . . . . +18: X . . X . . . X . . . . . . . . . . . . . . . . +19: . . . X . . . . . . . . . . . . . X X X . X . . +20: . . X . . . . . . . . . . . . . . . . X X X . . +21: X . . . . . . . . . . . . . . . . . . . X X . . +22: . . X . . . . . . . . . . . . . . . . . X X . . +23: . . . . . . X . . . . X . . . . . . . . . . . X +return value from amd_preprocess: 0 (should be 0) + +The column-oriented form of the sorted/transposed matrix R: + +Column: 0, number of entries: 4, with row indices in Ri [0 ... 3]: + row indices: 0 6 13 19 + +Column: 1, number of entries: 4, with row indices in Ri [4 ... 7]: + row indices: 1 8 9 14 + +Column: 2, number of entries: 3, with row indices in Ri [8 ... 10]: + row indices: 2 11 21 + +Column: 3, number of entries: 3, with row indices in Ri [11 ... 13]: + row indices: 3 7 15 + +Column: 4, number of entries: 2, with row indices in Ri [14 ... 15]: + row indices: 7 16 + +Column: 5, number of entries: 4, with row indices in Ri [16 ... 19]: + row indices: 0 5 6 12 + +Column: 6, number of entries: 5, with row indices in Ri [20 ... 24]: + row indices: 2 5 6 19 21 + +Column: 7, number of entries: 4, with row indices in Ri [25 ... 28]: + row indices: 3 4 7 9 + +Column: 8, number of entries: 2, with row indices in Ri [29 ... 30]: + row indices: 1 9 + +Column: 9, number of entries: 5, with row indices in Ri [31 ... 35]: + row indices: 4 7 8 14 18 + +Column: 10, number of entries: 5, with row indices in Ri [36 ... 40]: + row indices: 3 18 19 20 21 + +Column: 11, number of entries: 5, with row indices in Ri [41 ... 45]: + row indices: 2 6 12 21 23 + +Column: 12, number of entries: 5, with row indices in Ri [46 ... 50]: + row indices: 0 6 11 12 23 + +Column: 13, number of entries: 6, with row indices in Ri [51 ... 56]: + row indices: 0 1 5 9 13 17 + +Column: 14, number of entries: 5, with row indices in Ri [57 ... 61]: + row indices: 1 4 7 8 14 + +Column: 15, number of entries: 6, with row indices in Ri [62 ... 67]: + row indices: 3 4 7 15 16 18 + +Column: 16, number of entries: 4, with row indices in Ri [68 ... 71]: + row indices: 4 7 15 16 + +Column: 17, number of entries: 9, with row indices in Ri [72 ... 80]: + row indices: 0 1 5 7 9 13 17 18 19 + +Column: 18, number of entries: 3, with row indices in Ri [81 ... 83]: + row indices: 0 3 7 + +Column: 19, number of entries: 5, with row indices in Ri [84 ... 88]: + row indices: 3 17 18 19 21 + +Column: 20, number of entries: 4, with row indices in Ri [89 ... 92]: + row indices: 2 19 20 21 + +Column: 21, number of entries: 3, with row indices in Ri [93 ... 95]: + row indices: 0 20 21 + +Column: 22, number of entries: 3, with row indices in Ri [96 ... 98]: + row indices: 2 20 21 + +Column: 23, number of entries: 3, with row indices in Ri [99 ... 101]: + row indices: 6 11 23 + +Plot of the sorted/transposed matrix R: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X . . . . X . . . . . . X X . . . X X . . X . . + 1: . X . . . . . . X . . . . X X . . X . . . . . . + 2: . . X . . . X . . . . X . . . . . . . . X . X . + 3: . . . X . . . X . . X . . . . X . . X X . . . . + 4: . . . . . . . X . X . . . . X X X . . . . . . . + 5: . . . . . X X . . . . . . X . . . X . . . . . . + 6: X . . . . X X . . . . X X . . . . . . . . . . X + 7: . . . X X . . X . X . . . . X X X X X . . . . . + 8: . X . . . . . . . X . . . . X . . . . . . . . . + 9: . X . . . . . X X . . . . X . . . X . . . . . . +10: . . . . . . . . . . . . . . . . . . . . . . . . +11: . . X . . . . . . . . . X . . . . . . . . . . X +12: . . . . . X . . . . . X X . . . . . . . . . . . +13: X . . . . . . . . . . . . X . . . X . . . . . . +14: . X . . . . . . . X . . . . X . . . . . . . . . +15: . . . X . . . . . . . . . . . X X . . . . . . . +16: . . . . X . . . . . . . . . . X X . . . . . . . +17: . . . . . . . . . . . . . X . . . X . X . . . . +18: . . . . . . . . . X X . . . . X . X . X . . . . +19: X . . . . . X . . . X . . . . . . X . X X . . . +20: . . . . . . . . . . X . . . . . . . . . X X X . +21: . . X . . . X . . . X X . . . . . . . X X X X . +22: . . . . . . . . . . . . . . . . . . . . . . . . +23: . . . . . . . . . . . X X . . . . . . . . . . X + +Plot of symmetric matrix to be ordered by amd_order: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X . . . . X X . . . . . X X . . . X X X . X . . + 1: . X . . . . . . X X . . . X X . . X . . . . . . + 2: . . X . . . X . . . . X . . . . . . . . X X X . + 3: . . . X . . . X . . X . . . . X . . X X . . . . + 4: . . . . X . . X . X . . . . X X X . . . . . . . + 5: X . . . . X X . . . . . X X . . . X . . . . . . + 6: X . X . . X X . . . . X X . . . . . . X . X . X + 7: . . . X X . . X . X . . . . X X X X X . . . . . + 8: . X . . . . . . X X . . . . X . . . . . . . . . + 9: . X . . X . . X X X . . . X X . . X X . . . . . +10: . . . X . . . . . . X . . . . . . . X X X X . . +11: . . X . . . X . . . . X X . . . . . . . . X . X +12: X . . . . X X . . . . X X . . . . . . . . . . X +13: X X . . . X . . . X . . . X . . . X . . . . . . +14: . X . . X . . X X X . . . . X . . . . . . . . . +15: . . . X X . . X . . . . . . . X X . X . . . . . +16: . . . . X . . X . . . . . . . X X . . . . . . . +17: X X . . . X . X . X . . . X . . . X X X . . . . +18: X . . X . . . X . X X . . . . X . X X X . . . . +19: X . . X . . X . . . X . . . . . . X X X X X . . +20: . . X . . . . . . . X . . . . . . . . X X X X . +21: X . X . . . X . . . X X . . . . . . . X X X X . +22: . . X . . . . . . . . . . . . . . . . . X X X . +23: . . . . . . X . . . . X X . . . . . . . . . . X +return value from amd_order: 0 (should be 0) + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 24 + nz, number of nonzeros in A: 102 + symmetry of A: 0.4000 + number of nonzeros on diagonal: 17 + nonzeros in pattern of A+A' (excl. diagonal): 136 + # dense rows/columns of A+A': 0 + memory used, in bytes: 1516 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 97 + nonzeros in L (including diagonal): 121 + # divide operations for LDL' or LU: 97 + # multiply-subtract operations for LDL': 275 + # multiply-subtract operations for LU: 453 + max nz. in any column of L (incl. diagonal): 8 + + chol flop count for real A, sqrt counted as 1 flop: 671 + LDL' flop count for real A: 647 + LDL' flop count for complex A: 3073 + LU flop count for real A (with no pivoting): 1003 + LU flop count for complex A (with no pivoting): 4497 + +Permutation vector: + 22 20 10 23 12 5 16 8 14 4 15 7 1 9 13 17 0 2 3 6 11 18 21 19 + +Inverse permutation vector: + 16 12 17 18 9 5 19 11 7 13 2 20 4 14 8 10 6 15 21 23 1 22 0 3 + + +Plot of (symmetrized) permuted matrix pattern: + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + 0: X X . . . . . . . . . . . . . . . X . . . . X . + 1: X X X . . . . . . . . . . . . . . X . . . . X X + 2: . X X . . . . . . . . . . . . . . . X . . X X X + 3: . . . X X . . . . . . . . . . . . . . X X . . . + 4: . . . X X X . . . . . . . . . . X . . X X . . . + 5: . . . . X X . . . . . . . . X X X . . X . . . . + 6: . . . . . . X . . X X X . . . . . . . . . . . . + 7: . . . . . . . X X . . . X X . . . . . . . . . . + 8: . . . . . . . X X X . X X X . . . . . . . . . . + 9: . . . . . . X . X X X X . X . . . . . . . . . . +10: . . . . . . X . . X X X . . . . . . X . . X . . +11: . . . . . . X . X X X X . X . X . . X . . X . . +12: . . . . . . . X X . . . X X X X . . . . . . . . +13: . . . . . . . X X X . X X X X X . . . . . X . . +14: . . . . . X . . . . . . X X X X X . . . . . . . +15: . . . . . X . . . . . X X X X X X . . . . X . X +16: . . . . X X . . . . . . . . X X X . . X . X X X +17: X X . . . . . . . . . . . . . . . X . X X . X . +18: . . X . . . . . . . X X . . . . . . X . . X . X +19: . . . X X X . . . . . . . . . . X X . X X . X X +20: . . . X X . . . . . . . . . . . . X . X X . X . +21: . . X . . . . . . . X X . X . X X . X . . X . X +22: X X X . . . . . . . . . . . . . X X . X X . X X +23: . X X . . . . . . . . . . . . X X . X X . X X X diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77cross.f b/liboctave/UMFPACK/AMD/Demo/amd_f77cross.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77cross.f @@ -0,0 +1,51 @@ +C ====================================================================== +C === AMD_cross ======================================================== +C ====================================================================== + +C ---------------------------------------------------------------------- +C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. +C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for +C License. email: davis@cise.ufl.edu CISE Department, Univ. of +C Florida. web: http://www.cise.ufl.edu/research/sparse/amd +C ---------------------------------------------------------------------- + +C This program provides an example of how to call the C version of AMD +C from a Fortran program. It is HIGHLY non-portable. + +C The amd_order routine returns PERM (1) < 0 if an error occurs. +C (-1: out of memory, -2: invalid matrix) + +C Note that the input matrix is 0-based. From Fortran, column j of the +C matrix is in AI (AP (I)+1 ... AP (I+1)). The row indices in this +C set are in the range 0 to N-1. To demonstrate this translation, +C the input matrix is printed in 1-based form. This program uses +C the same 5-by-5 test matrix as amd_simple.c. + + INTEGER N, NZ, K, P + PARAMETER (N = 5, NZ = 14) + INTEGER AP (N+1), AI (NZ), PERM (N) + DATA AP / 0, 2, 6, 10, 12, 14 / + DATA AI / 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 / + DOUBLE PRECISION CONTROL (5), INFO (20) + +C print the input matrix + PRINT 10, N, N, NZ +10 FORMAT ('Input matrix:', I2, '-by-', I2, ' with',I3,' entries') + DO 40 J = 1, N + PRINT 20, J, AP (J+1) - AP (J), AP (J)+1, AP (J+1) +20 FORMAT ( /, 'Column: ', I2, ' number of entries: ', I2, + $ ' with row indices in AI (', I3, ' ... ', I3, ')') + PRINT 30, ((AI (P) + 1), P = AP (J) + 1, AP (J+1)) +30 FORMAT (' row indices: ', 24I3) +40 CONTINUE + + CALL AMDDEFAULTS (CONTROL) + CALL AMDORDER (N, AP, AI, PERM, CONTROL, INFO) + CALL AMDINFO (INFO) + + DO 60 K = 1, N + PRINT 50, K, PERM (K) + 1 +50 FORMAT ('PERM (',I2,') = ', I2) +60 CONTINUE + END + diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77cross.out b/liboctave/UMFPACK/AMD/Demo/amd_f77cross.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77cross.out @@ -0,0 +1,51 @@ +Input matrix: 5-by- 5 with 14 entries + +Column: 1 number of entries: 2 with row indices in AI ( 1 ... 2) + row indices: 1 2 + +Column: 2 number of entries: 4 with row indices in AI ( 3 ... 6) + row indices: 1 2 3 5 + +Column: 3 number of entries: 4 with row indices in AI ( 7 ... 10) + row indices: 2 3 4 5 + +Column: 4 number of entries: 2 with row indices in AI ( 11 ... 12) + row indices: 3 4 + +Column: 5 number of entries: 2 with row indices in AI ( 13 ... 14) + row indices: 2 5 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 5 + nz, number of nonzeros in A: 14 + symmetry of A: 0.8889 + number of nonzeros on diagonal: 5 + nonzeros in pattern of A+A' (excl. diagonal): 10 + # dense rows/columns of A+A': 0 + memory used, in bytes: 228 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 5 + nonzeros in L (including diagonal): 10 + # divide operations for LDL' or LU: 5 + # multiply-subtract operations for LDL': 6 + # multiply-subtract operations for LU: 7 + max nz. in any column of L (incl. diagonal): 3 + + chol flop count for real A, sqrt counted as 1 flop: 22 + LDL' flop count for real A: 17 + LDL' flop count for complex A: 93 + LU flop count for real A (with no pivoting): 19 + LU flop count for complex A (with no pivoting): 101 + +PERM ( 1) = 1 +PERM ( 2) = 4 +PERM ( 3) = 3 +PERM ( 4) = 5 +PERM ( 5) = 2 diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77demo.f b/liboctave/UMFPACK/AMD/Demo/amd_f77demo.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77demo.f @@ -0,0 +1,161 @@ +C ====================================================================== +C === Fortran AMD demo main program ==================================== +C ====================================================================== + +C ---------------------------------------------------------------------- +C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. +C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for +C License. email: davis@cise.ufl.edu CISE Department, Univ. of +C Florida. web: http://www.cise.ufl.edu/research/sparse/amd +C ---------------------------------------------------------------------- + +C A simple Fortran 77 main program that illustrates the use of the +C Fortran version of AMD (both the AMD and AMDBAR routines). Note +C that aggressive absorption has no effect on this particular matrix. + +C AP and AI contain the symmetric can_24 Harwell/Boeing matrix, +C including upper and lower triangular parts, but excluding the +C diagonal entries. Note that this matrix is 1-based, with row +C and column indices in the range 1 to N. + + INTEGER N, NZ, IWLEN, PFREE, I, J, K, JNEW, P, INEW, + $ METHOD, NCMPA + PARAMETER (N = 24, NZ = 136, IWLEN = 200) + INTEGER PE (N), DEGREE (N), NV (N), NEXT (N), PERM (N), W (N), + $ HEAD (N), PINV (N), LEN (N), AP (N+1), AI (NZ), IW (IWLEN) + CHARACTER A (24,24) + + DATA AP + $ / 1, 9, 14, 19, 24, 29, 34, 42, 50, 53, 61, 66, 71, + $ 76, 81, 86, 91, 94, 102, 110, 118, 123, 131, 134, 137 / + DATA AI / + $ 6, 7, 13, 14, 18, 19, 20, 22, + $ 9, 10, 14, 15, 18, + $ 7, 12, 21, 22, 23, + $ 8, 11, 16, 19, 20, + $ 8, 10, 15, 16, 17, + $ 1, 7, 13, 14, 18, + $ 1, 3, 6, 12, 13, 20, 22, 24, + $ 4, 5, 10, 15, 16, 17, 18, 19, + $ 2, 10, 15, + $ 2, 5, 8, 9, 14, 15, 18, 19, + $ 4, 19, 20, 21, 22, + $ 3, 7, 13, 22, 24, + $ 1, 6, 7, 12, 24, + $ 1, 2, 6, 10, 18, + $ 2, 5, 8, 9, 10, + $ 4, 5, 8, 17, 19, + $ 5, 8, 16, + $ 1, 2, 6, 8, 10, 14, 19, 20, + $ 1, 4, 8, 10, 11, 16, 18, 20, + $ 1, 4, 7, 11, 18, 19, 21, 22, + $ 3, 11, 20, 22, 23, + $ 1, 3, 7, 11, 12, 20, 21, 23, + $ 3, 21, 22, + $ 7, 12, 13 / + +C print the input matrix + PRINT 11, N, N, NZ +11 FORMAT ('AMD Fortran 77 demo, with the 24-by-24', + $ ' Harwell/Boeing matrix, can_24:' + $ /, 'Input matrix: ', I2, '-by-', I2,' with ',I3,' entries', + $ /, 'Note that the Fortran version of AMD requires that' + $ /, 'no diagonal entries be present.') + DO 20 J = 1, N + PRINT 21, J, AP (J+1) - AP (J), AP (J), AP (J+1)-1 +21 FORMAT ( /, 'Column: ', I2, ' number of entries: ', I2, + $ ' with row indices in AI (', I3, ' ... ', I3, ')') + PRINT 10, ((AI (P)), P = AP (J), AP (J+1) - 1) +10 FORMAT (' row indices: ', 24I3) +20 CONTINUE + +C print a character plot of the input matrix. This is only +C reasonable because the matrix is small. + PRINT 31 +31 FORMAT ('Plot of input matrix pattern:') + DO 50 J = 1,N + DO 30 I = 1,N + A (I, J) = '.' +30 CONTINUE +C add the diagonal entry to the plot + A (J, J) = 'X' + DO 40 P = AP (J), AP (J+1) - 1 + I = AI (P) + A (I, J) = 'X' +40 CONTINUE +50 CONTINUE + PRINT 60, ((MOD (J, 10)), J = 1,N) +60 FORMAT (' ', 24I2) + DO 80 I = 1,N + PRINT 70, I, (A (I, J), J = 1,N) +70 FORMAT (' ', I2, ': ', 24A2) +80 CONTINUE + + DO 190 METHOD = 1,2 + +C load the matrix into AMD's workspace + DO 90 J = 1,N + PE (J) = AP (J) + LEN (J) = AP (J+1) - AP (J) +90 CONTINUE + DO 100 P = 1,NZ + IW (P) = AI (P) +100 CONTINUE + PFREE = NZ + 1 + +C order the matrix using AMD or AMDBAR + IF (METHOD .EQ. 1) THEN + PRINT 101 +101 FORMAT (/, '------------------------------------------', + $ /, 'ordering the matrix with AMD', + $ /, '------------------------------------------') + CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, + $ PERM, HEAD, PINV, DEGREE, NCMPA, W) + ELSE + PRINT 102 +102 FORMAT (/, '------------------------------------------', + $ /, 'ordering the matrix with AMDBAR', + $ /, '------------------------------------------') + CALL AMDBAR (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, + $ PERM, HEAD, PINV, DEGREE, NCMPA, W) + ENDIF + +C print the permutation vector, PERM, and its inverse, PINV. +C row/column J = PERM (K) is the Kth row/column in the +C permuted matrix. + PRINT 110, (PERM (K), K = 1,N) +110 FORMAT (/, 'Permutation vector: ', /, 24I3) + PRINT 120, (PINV (J), J = 1,N) +120 FORMAT (/, 'Inverse permutation vector: ', /, 24I3) + +C print a character plot of the permuted matrix. + PRINT 121 +121 FORMAT ('Plot of permuted matrix pattern:') + DO 150 JNEW = 1,N + J = PERM (JNEW) + DO 130 INEW = 1,N + A (INEW, JNEW) = '.' +130 CONTINUE +C add the diagonal entry to the plot + A (JNEW, JNEW) = 'X' + DO 140 P = AP (J), AP (J+1) - 1 + INEW = PINV (AI (P)) + A (INEW, JNEW) = 'X' +140 CONTINUE +150 CONTINUE + PRINT 60, ((MOD (J, 10)), J = 1,N) + DO 160 I = 1,N + PRINT 70, I, (A (I, J), J = 1,N) +160 CONTINUE + +C print the permuted matrix, PERM*A*PERM' + DO 180 JNEW = 1,N + J = PERM (JNEW) + PRINT 171, JNEW, J, AP (J+1) - AP (J) +171 FORMAT (/, 'New column: ', I2, ' old column: ', I2, + $ ' number of entries: ', I2) + PRINT 170, (PINV (AI (P)), P = AP (J), AP (J+1) - 1) +170 FORMAT (' new row indices: ', 24I3) +180 CONTINUE +190 CONTINUE + END diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77demo.out b/liboctave/UMFPACK/AMD/Demo/amd_f77demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77demo.out @@ -0,0 +1,318 @@ +AMD Fortran 77 demo, with the 24-by-24 Harwell/Boeing matrix, can_24: +Input matrix: 24-by-24 with 136 entries +Note that the Fortran version of AMD requires that +no diagonal entries be present. + +Column: 1 number of entries: 8 with row indices in AI ( 1 ... 8) + row indices: 6 7 13 14 18 19 20 22 + +Column: 2 number of entries: 5 with row indices in AI ( 9 ... 13) + row indices: 9 10 14 15 18 + +Column: 3 number of entries: 5 with row indices in AI ( 14 ... 18) + row indices: 7 12 21 22 23 + +Column: 4 number of entries: 5 with row indices in AI ( 19 ... 23) + row indices: 8 11 16 19 20 + +Column: 5 number of entries: 5 with row indices in AI ( 24 ... 28) + row indices: 8 10 15 16 17 + +Column: 6 number of entries: 5 with row indices in AI ( 29 ... 33) + row indices: 1 7 13 14 18 + +Column: 7 number of entries: 8 with row indices in AI ( 34 ... 41) + row indices: 1 3 6 12 13 20 22 24 + +Column: 8 number of entries: 8 with row indices in AI ( 42 ... 49) + row indices: 4 5 10 15 16 17 18 19 + +Column: 9 number of entries: 3 with row indices in AI ( 50 ... 52) + row indices: 2 10 15 + +Column: 10 number of entries: 8 with row indices in AI ( 53 ... 60) + row indices: 2 5 8 9 14 15 18 19 + +Column: 11 number of entries: 5 with row indices in AI ( 61 ... 65) + row indices: 4 19 20 21 22 + +Column: 12 number of entries: 5 with row indices in AI ( 66 ... 70) + row indices: 3 7 13 22 24 + +Column: 13 number of entries: 5 with row indices in AI ( 71 ... 75) + row indices: 1 6 7 12 24 + +Column: 14 number of entries: 5 with row indices in AI ( 76 ... 80) + row indices: 1 2 6 10 18 + +Column: 15 number of entries: 5 with row indices in AI ( 81 ... 85) + row indices: 2 5 8 9 10 + +Column: 16 number of entries: 5 with row indices in AI ( 86 ... 90) + row indices: 4 5 8 17 19 + +Column: 17 number of entries: 3 with row indices in AI ( 91 ... 93) + row indices: 5 8 16 + +Column: 18 number of entries: 8 with row indices in AI ( 94 ... 101) + row indices: 1 2 6 8 10 14 19 20 + +Column: 19 number of entries: 8 with row indices in AI (102 ... 109) + row indices: 1 4 8 10 11 16 18 20 + +Column: 20 number of entries: 8 with row indices in AI (110 ... 117) + row indices: 1 4 7 11 18 19 21 22 + +Column: 21 number of entries: 5 with row indices in AI (118 ... 122) + row indices: 3 11 20 22 23 + +Column: 22 number of entries: 8 with row indices in AI (123 ... 130) + row indices: 1 3 7 11 12 20 21 23 + +Column: 23 number of entries: 3 with row indices in AI (131 ... 133) + row indices: 3 21 22 + +Column: 24 number of entries: 3 with row indices in AI (134 ... 136) + row indices: 7 12 13 +Plot of input matrix pattern: + 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 + 1: X . . . . X X . . . . . X X . . . X X X . X . . + 2: . X . . . . . . X X . . . X X . . X . . . . . . + 3: . . X . . . X . . . . X . . . . . . . . X X X . + 4: . . . X . . . X . . X . . . . X . . X X . . . . + 5: . . . . X . . X . X . . . . X X X . . . . . . . + 6: X . . . . X X . . . . . X X . . . X . . . . . . + 7: X . X . . X X . . . . X X . . . . . . X . X . X + 8: . . . X X . . X . X . . . . X X X X X . . . . . + 9: . X . . . . . . X X . . . . X . . . . . . . . . + 10: . X . . X . . X X X . . . X X . . X X . . . . . + 11: . . . X . . . . . . X . . . . . . . X X X X . . + 12: . . X . . . X . . . . X X . . . . . . . . X . X + 13: X . . . . X X . . . . X X . . . . . . . . . . X + 14: X X . . . X . . . X . . . X . . . X . . . . . . + 15: . X . . X . . X X X . . . . X . . . . . . . . . + 16: . . . X X . . X . . . . . . . X X . X . . . . . + 17: . . . . X . . X . . . . . . . X X . . . . . . . + 18: X X . . . X . X . X . . . X . . . X X X . . . . + 19: X . . X . . . X . X X . . . . X . X X X . . . . + 20: X . . X . . X . . . X . . . . . . X X X X X . . + 21: . . X . . . . . . . X . . . . . . . . X X X X . + 22: X . X . . . X . . . X X . . . . . . . X X X X . + 23: . . X . . . . . . . . . . . . . . . . . X X X . + 24: . . . . . . X . . . . X X . . . . . . . . . . X + +------------------------------------------ +ordering the matrix with AMD +------------------------------------------ + +Permutation vector: + 24 23 17 9 15 5 21 13 6 11 16 8 2 10 14 18 1 3 4 19 7 12 22 20 + +Inverse permutation vector: + 17 13 18 19 6 9 21 12 4 14 10 22 8 15 5 11 3 16 20 24 7 23 2 1 +Plot of permuted matrix pattern: + 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 + 1: X . . . . . . X . . . . . . . . . . . . X X . . + 2: . X . . . . X . . . . . . . . . . X . . . . X . + 3: . . X . . X . . . . X X . . . . . . . . . . . . + 4: . . . X X . . . . . . . X X . . . . . . . . . . + 5: . . . X X X . . . . . X X X . . . . . . . . . . + 6: . . X . X X . . . . X X . X . . . . . . . . . . + 7: . X . . . . X . . X . . . . . . . X . . . . X X + 8: X . . . . . . X X . . . . . . . X . . . X X . . + 9: . . . . . . . X X . . . . . X X X . . . X . . . + 10: . . . . . . X . . X . . . . . . . . X X . . X X + 11: . . X . . X . . . . X X . . . . . . X X . . . . + 12: . . X . X X . . . . X X . X . X . . X X . . . . + 13: . . . X X . . . . . . . X X X X . . . . . . . . + 14: . . . X X X . . . . . X X X X X . . . X . . . . + 15: . . . . . . . . X . . . X X X X X . . . . . . . + 16: . . . . . . . . X . . X X X X X X . . X . . . X + 17: . . . . . . . X X . . . . . X X X . . X X . X X + 18: . X . . . . X . . . . . . . . . . X . . X X X . + 19: . . . . . . . . . X X X . . . . . . X X . . . X + 20: . . . . . . . . . X X X . X . X X . X X . . . X + 21: X . . . . . . X X . . . . . . . X X . . X X X X + 22: X . . . . . . X . . . . . . . . . X . . X X X . + 23: . X . . . . X . . X . . . . . . X X . . X X X X + 24: . . . . . . X . . X . . . . . X X . X X X . X X + +New column: 1 old column: 24 number of entries: 3 + new row indices: 21 22 8 + +New column: 2 old column: 23 number of entries: 3 + new row indices: 18 7 23 + +New column: 3 old column: 17 number of entries: 3 + new row indices: 6 12 11 + +New column: 4 old column: 9 number of entries: 3 + new row indices: 13 14 5 + +New column: 5 old column: 15 number of entries: 5 + new row indices: 13 6 12 4 14 + +New column: 6 old column: 5 number of entries: 5 + new row indices: 12 14 5 11 3 + +New column: 7 old column: 21 number of entries: 5 + new row indices: 18 10 24 23 2 + +New column: 8 old column: 13 number of entries: 5 + new row indices: 17 9 21 22 1 + +New column: 9 old column: 6 number of entries: 5 + new row indices: 17 21 8 15 16 + +New column: 10 old column: 11 number of entries: 5 + new row indices: 19 20 24 7 23 + +New column: 11 old column: 16 number of entries: 5 + new row indices: 19 6 12 3 20 + +New column: 12 old column: 8 number of entries: 8 + new row indices: 19 6 14 5 11 3 16 20 + +New column: 13 old column: 2 number of entries: 5 + new row indices: 4 14 15 5 16 + +New column: 14 old column: 10 number of entries: 8 + new row indices: 13 6 12 4 15 5 16 20 + +New column: 15 old column: 14 number of entries: 5 + new row indices: 17 13 9 14 16 + +New column: 16 old column: 18 number of entries: 8 + new row indices: 17 13 9 12 14 15 20 24 + +New column: 17 old column: 1 number of entries: 8 + new row indices: 9 21 8 15 16 20 24 23 + +New column: 18 old column: 3 number of entries: 5 + new row indices: 21 22 7 23 2 + +New column: 19 old column: 4 number of entries: 5 + new row indices: 12 10 11 20 24 + +New column: 20 old column: 19 number of entries: 8 + new row indices: 17 19 12 14 10 11 16 24 + +New column: 21 old column: 7 number of entries: 8 + new row indices: 17 18 9 22 8 24 23 1 + +New column: 22 old column: 12 number of entries: 5 + new row indices: 18 21 8 23 1 + +New column: 23 old column: 22 number of entries: 8 + new row indices: 17 18 21 10 22 24 7 2 + +New column: 24 old column: 20 number of entries: 8 + new row indices: 17 19 21 10 16 20 7 23 + +------------------------------------------ +ordering the matrix with AMDBAR +------------------------------------------ + +Permutation vector: + 24 23 17 9 15 5 21 13 6 11 16 8 2 10 14 18 1 3 4 19 7 12 22 20 + +Inverse permutation vector: + 17 13 18 19 6 9 21 12 4 14 10 22 8 15 5 11 3 16 20 24 7 23 2 1 +Plot of permuted matrix pattern: + 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 + 1: X . . . . . . X . . . . . . . . . . . . X X . . + 2: . X . . . . X . . . . . . . . . . X . . . . X . + 3: . . X . . X . . . . X X . . . . . . . . . . . . + 4: . . . X X . . . . . . . X X . . . . . . . . . . + 5: . . . X X X . . . . . X X X . . . . . . . . . . + 6: . . X . X X . . . . X X . X . . . . . . . . . . + 7: . X . . . . X . . X . . . . . . . X . . . . X X + 8: X . . . . . . X X . . . . . . . X . . . X X . . + 9: . . . . . . . X X . . . . . X X X . . . X . . . + 10: . . . . . . X . . X . . . . . . . . X X . . X X + 11: . . X . . X . . . . X X . . . . . . X X . . . . + 12: . . X . X X . . . . X X . X . X . . X X . . . . + 13: . . . X X . . . . . . . X X X X . . . . . . . . + 14: . . . X X X . . . . . X X X X X . . . X . . . . + 15: . . . . . . . . X . . . X X X X X . . . . . . . + 16: . . . . . . . . X . . X X X X X X . . X . . . X + 17: . . . . . . . X X . . . . . X X X . . X X . X X + 18: . X . . . . X . . . . . . . . . . X . . X X X . + 19: . . . . . . . . . X X X . . . . . . X X . . . X + 20: . . . . . . . . . X X X . X . X X . X X . . . X + 21: X . . . . . . X X . . . . . . . X X . . X X X X + 22: X . . . . . . X . . . . . . . . . X . . X X X . + 23: . X . . . . X . . X . . . . . . X X . . X X X X + 24: . . . . . . X . . X . . . . . X X . X X X . X X + +New column: 1 old column: 24 number of entries: 3 + new row indices: 21 22 8 + +New column: 2 old column: 23 number of entries: 3 + new row indices: 18 7 23 + +New column: 3 old column: 17 number of entries: 3 + new row indices: 6 12 11 + +New column: 4 old column: 9 number of entries: 3 + new row indices: 13 14 5 + +New column: 5 old column: 15 number of entries: 5 + new row indices: 13 6 12 4 14 + +New column: 6 old column: 5 number of entries: 5 + new row indices: 12 14 5 11 3 + +New column: 7 old column: 21 number of entries: 5 + new row indices: 18 10 24 23 2 + +New column: 8 old column: 13 number of entries: 5 + new row indices: 17 9 21 22 1 + +New column: 9 old column: 6 number of entries: 5 + new row indices: 17 21 8 15 16 + +New column: 10 old column: 11 number of entries: 5 + new row indices: 19 20 24 7 23 + +New column: 11 old column: 16 number of entries: 5 + new row indices: 19 6 12 3 20 + +New column: 12 old column: 8 number of entries: 8 + new row indices: 19 6 14 5 11 3 16 20 + +New column: 13 old column: 2 number of entries: 5 + new row indices: 4 14 15 5 16 + +New column: 14 old column: 10 number of entries: 8 + new row indices: 13 6 12 4 15 5 16 20 + +New column: 15 old column: 14 number of entries: 5 + new row indices: 17 13 9 14 16 + +New column: 16 old column: 18 number of entries: 8 + new row indices: 17 13 9 12 14 15 20 24 + +New column: 17 old column: 1 number of entries: 8 + new row indices: 9 21 8 15 16 20 24 23 + +New column: 18 old column: 3 number of entries: 5 + new row indices: 21 22 7 23 2 + +New column: 19 old column: 4 number of entries: 5 + new row indices: 12 10 11 20 24 + +New column: 20 old column: 19 number of entries: 8 + new row indices: 17 19 12 14 10 11 16 24 + +New column: 21 old column: 7 number of entries: 8 + new row indices: 17 18 9 22 8 24 23 1 + +New column: 22 old column: 12 number of entries: 5 + new row indices: 18 21 8 23 1 + +New column: 23 old column: 22 number of entries: 8 + new row indices: 17 18 21 10 22 24 7 2 + +New column: 24 old column: 20 number of entries: 8 + new row indices: 17 19 21 10 16 20 7 23 diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77simple.f b/liboctave/UMFPACK/AMD/Demo/amd_f77simple.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77simple.f @@ -0,0 +1,38 @@ +C ---------------------------------------------------------------------- +C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. +C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for +C License. email: davis@cise.ufl.edu CISE Department, Univ. of +C Florida. web: http://www.cise.ufl.edu/research/sparse/amd +C ---------------------------------------------------------------------- + +C This program provides an example of how to call the Fortran version +C of AMD. It uses the same matrix as the amd_simple.c demo (in C). +C Note that the diagonal entries are not present, and the matrix is +C symmetric. + + INTEGER N, NZ, J, K, P, IWLEN, PFREE, NCMPA + PARAMETER (N = 5, NZ = 10, IWLEN = 17) + INTEGER AP (N+1), AI (NZ), LAST (N), PE (N), LEN (N), ELEN (N), + $ IW (IWLEN), DEGREE (N), NV (N), NEXT (N), HEAD (N), W (N) + DATA AP / 1, 2, 5, 8, 9, 11/ + DATA AI / 2, 1,3,5, 2,4,5, 3, 2,3 / + +C load the matrix into the AMD workspace + DO 10 J = 1,N + PE (J) = AP (J) + LEN (J) = AP (J+1) - AP (J) +10 CONTINUE + DO 20 P = 1,NZ + IW (P) = AI (P) +20 CONTINUE + PFREE = NZ + 1 + +C order the matrix (destroys the copy of A in IW, PE, and LEN) + CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, LAST, HEAD, + $ ELEN, DEGREE, NCMPA, W) + + DO 60 K = 1, N + PRINT 50, K, LAST (K) +50 FORMAT ('P (',I2,') = ', I2) +60 CONTINUE + END diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77simple.out b/liboctave/UMFPACK/AMD/Demo/amd_f77simple.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77simple.out @@ -0,0 +1,5 @@ +P ( 1) = 4 +P ( 2) = 1 +P ( 3) = 3 +P ( 4) = 5 +P ( 5) = 2 diff --git a/liboctave/UMFPACK/AMD/Demo/amd_f77wrapper.c b/liboctave/UMFPACK/AMD/Demo/amd_f77wrapper.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_f77wrapper.c @@ -0,0 +1,108 @@ +/* ========================================================================= */ +/* === amd_f77wrapper ====================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Fortran interface for the C-callable AMD library (int version only). This + * is HIGHLY non-portable. You will need to modify this depending on how your + * Fortran and C compilers behave. Two examples are provided. + * + * To avoid using I/O, and to avoid the extra porting step of a Fortran + * function, the status code is returned as the first entry in P (P [0] in C + * and P (1) in Fortran) if an error occurs. The error codes are negative + * (-1: out of memory, -2: invalid matrix). + * + * For some C and Fortran compilers, the Fortran compiler appends a single "_" + * after each routine name. C doesn't do this, so the translation is made + * here. Some Fortran compilers don't append an underscore (xlf on IBM AIX, + * for * example). + * + * Tested with the following compilers: + * Solaris with cc and f77 from Sun WorkShop 6 update 1. + * SGI Irix with MIPSpro cc and f77 compilers version 7.4 + * Linux with GNU gcc or Intel's icc, and GNU g77 Intel's ifc Fortran compiler. + * (any combination). Note that with g77, a call to amd_order in Fortran + * gets translated to a call to amd_order__, with two underscores ("_"). + * Thus, the Fortran names do not include an underscore. + */ + +#include "amd.h" +#include + +/* ------------------------------------------------------------------------- */ +/* Linux, Solaris, SGI */ +/* ------------------------------------------------------------------------- */ + +void amdorder_ (int *n, const int *Ap, const int *Ai, int *P, + double *Control, double *Info) +{ + int result = amd_order (*n, Ap, Ai, P, Control, Info) ; + if (result != AMD_OK && P) P [0] = result ; +} + +void amddefaults_ (double *Control) +{ + amd_defaults (Control) ; +} + +void amdcontrol_ (double *Control) +{ + fflush (stdout) ; + amd_control (Control) ; + fflush (stdout) ; +} + +void amdinfo_ (double *Info) +{ + fflush (stdout) ; + amd_info (Info) ; + fflush (stdout) ; +} + +void amdpreproc_ (int *n, const int *Ap, const int *Ai, int *Rp, int *Ri) +{ + int result = amd_preprocess (*n, Ap, Ai, Rp, Ri) ; + if (result != AMD_OK && Rp) Rp [0] = result ; +} + +/* ------------------------------------------------------------------------- */ +/* IBM AIX. Probably Windows, Compaq Alpha, and HP Unix as well. */ +/* ------------------------------------------------------------------------- */ + +void amdorder (int *n, const int *Ap, const int *Ai, int *P, + double *Control, double *Info) +{ + int result = amd_order (*n, Ap, Ai, P, Control, Info) ; + if (result != AMD_OK && P) P [0] = result ; +} + +void amddefaults (double *Control) +{ + amd_defaults (Control) ; +} + +void amdcontrol (double *Control) +{ + fflush (stdout) ; + amd_control (Control) ; + fflush (stdout) ; +} + +void amdinfo (double *Info) +{ + fflush (stdout) ; + amd_info (Info) ; + fflush (stdout) ; +} + +void amdpreproc (int *n, const int *Ap, const int *Ai, int *Rp, int *Ri) +{ + int result = amd_preprocess (*n, Ap, Ai, Rp, Ri) ; + if (result != AMD_OK && Rp) Rp [0] = result ; +} diff --git a/liboctave/UMFPACK/AMD/Demo/amd_simple.c b/liboctave/UMFPACK/AMD/Demo/amd_simple.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_simple.c @@ -0,0 +1,23 @@ +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +#include +#include "amd.h" + +int n = 5 ; +int Ap [ ] = { 0, 2, 6, 10, 12, 14} ; +int Ai [ ] = { 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 } ; +int P [5] ; + +int main (void) +{ + int k ; + (void) amd_order (n, Ap, Ai, P, (double *) NULL, (double *) NULL) ; + for (k = 0 ; k < n ; k++) printf ("P [%d] = %d\n", k, P [k]) ; + return (0) ; +} + diff --git a/liboctave/UMFPACK/AMD/Demo/amd_simple.out b/liboctave/UMFPACK/AMD/Demo/amd_simple.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Demo/amd_simple.out @@ -0,0 +1,5 @@ +P [0] = 0 +P [1] = 3 +P [2] = 2 +P [3] = 4 +P [4] = 1 diff --git a/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.bib b/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.bib new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.bib @@ -0,0 +1,86 @@ +@string{SIREV = "{SIAM} Review"} +@string{SIMAX = "{SIAM} J. Matrix Anal. Applic."} +@string{SIAMJSC = "{SIAM} J. Sci. Comput."} +@string{TOMS = "{ACM} Trans. Math. Softw."} + +@article{schu:01, + author = {J. Schulze}, + title = {Towards a tighter coupling of bottom-up and top-down sparse matrix ordering methods}, + journal = {BIT}, + volume = {41}, + number = {4}, + pages = "800--841", + year = {2001} + } + +@article{GeorgeLiu89, + author={George, A. and Liu, J. W. H.}, + year={1989}, + title={The Evolution of the Minimum Degree Ordering Algorithm}, + journal=SIREV, + volume={31}, + number={1}, + pages={1--19}} + +@article{AmestoyDavisDuff96, + author={Amestoy, P. R. and Davis, T. A. and Duff, I. S.}, + title={An approximate minimum degree ordering algorithm}, + journal=SIMAX, + year={1996} + ,volume={17} + ,number={4} + ,pages={886-905} + } + +@misc{hsl:2002, + author = {HSL}, + title = "{HSL} 2002: {A} collection of {F}ortran codes for large + scale scientific computation", + note = {{\tt www.cse.clrc.ac.uk/nag/hsl}}, + year = 2002} + + +@article{RothbergEisenstat98, + author={Rothberg, E. and Eisenstat, S. C.}, + title={Node selection strategies for bottom-up sparse matrix orderings}, + journal=SIMAX, + year={1998} + ,volume={19} + ,number={3} + ,pages={682-695} + } + +@article{KarypisKumar98e, + author={Karypis, G. and Kumar, V.}, + title={A fast and high quality multilevel scheme for partitioning irregular graphs}, + journal=SIAMJSC, + year={1998} + ,volume={20} + ,pages={359-392} + } + +@article{Chaco, + author={B. Hendrickson and E. Rothberg}, + title={Improving the runtime and quality of nested dissection ordering}, + journal=SIAMJSC, + year={1999} + ,volume={20} + ,pages={468--489} + } + +@article{PellegriniRomanAmestoy00, + author={Pellegrini, F. and Roman, J. and Amestoy, P.}, + title={Hybridizing nested dissection and halo approximate minimum degree for efficient sparse matrix ordering}, + journal={Concurrency: Practice and Experience}, + year={2000} + ,volume={12} + ,pages={68-84} + } + +@article{DavisGilbertLarimoreNg00pending, + author={Davis, T. A. and Gilbert, J. R. and Larimore, S. I. and Ng, E. G.}, + title={A column approximate minimum degree ordering algorithm}, + journal=TOMS, + year={(to appear)} + } + diff --git a/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.pdf b/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.pdf new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..39ca0b2abf6963a3f7b1908c4651e38af510297f GIT binary patch literal 176601 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%0AV=naF$@3OV2(!UGzZsam_= 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 diff --git a/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.tex b/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.tex new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.tex @@ -0,0 +1,1138 @@ +\documentclass[11pt]{article} + +\newcommand{\m}[1]{{\bf{#1}}} % for matrices and vectors +\newcommand{\tr}{^{\sf T}} % transpose + +\topmargin 0in +\textheight 9in +\oddsidemargin 0pt +\evensidemargin 0pt +\textwidth 6.5in + +%------------------------------------------------------------------------------ +\begin{document} +%------------------------------------------------------------------------------ + +\title{AMD Version 1.1 User Guide} +\author{Patrick R. Amestoy\thanks{ENSEEIHT-IRIT, +2 rue Camichel 31017 Toulouse, France. +email: amestoy@enseeiht.fr. http://www.enseeiht.fr/$\sim$amestoy.} +\and Timothy A. Davis\thanks{ +Dept.~of Computer and Information Science and Engineering, +Univ.~of Florida, Gainesville, FL, USA. +email: davis@cise.ufl.edu. +http://www.cise.ufl.edu/$\sim$davis. +This work was supported by the National +Science Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. +Portions of the work were done while on sabbatical at Stanford University +and Lawrence Berkeley National Laboratory (with funding from Stanford +University and the SciDAC program). +} +\and Iain S. Duff\thanks{Rutherford Appleton Laboratory, Chilton, Didcot, +Oxon OX11 0QX, England. email: i.s.duff@rl.ac.uk. +http://www.numerical.rl.ac.uk/people/isd/isd.html. +This work was supported by the EPSRC under grant GR/R46441. +}} + +\date{January 29, 2004} +\maketitle + +%------------------------------------------------------------------------------ +\begin{abstract} +AMD is a set of routines that implements the approximate minimum degree ordering +algorithm to permute sparse matrices prior to +numerical factorization. +There are versions written in both C and Fortran 77. +A MATLAB interface is included. +\end{abstract} +%------------------------------------------------------------------------------ + +Technical report TR-04-002, CISE Department, University of Florida, +Gainesville, FL, 2004. + +AMD Version 1.1 (Jan. 21, 2004), Copyright\copyright 2004 by Timothy A. +Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +{\bf AMD License:} + Your use or distribution of AMD or any modified version of + AMD implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses AMD or any modified version of AMD code must cite the + Copyright, this License, the Availability note, and ``Used by permission.'' + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +{\bf Availability:} + http://www.cise.ufl.edu/research/sparse/amd + +{\bf Acknowledgments:} + + This work was supported by the National Science Foundation, under + grants ASC-9111263 and DMS-9223088 and CCR-0203270. + The conversion to C, the addition of the elimination tree + post-ordering, and the handling of dense rows and columns + were done while Davis was on sabbatical at + Stanford University and Lawrence Berkeley National Laboratory. + +%------------------------------------------------------------------------------ +\newpage +\section{Overview} +%------------------------------------------------------------------------------ + +AMD is a set of routines for preordering a sparse matrix prior to +numerical factorization. It uses an approximate minimum degree ordering +algorithm \cite{AmestoyDavisDuff96} to find a permutation matrix $\m{P}$ +so that the Cholesky factorization $\m{PAP}\tr=\m{LL}\tr$ has fewer +(often much fewer) nonzero entries than the Cholesky factorization of $\m{A}$. +The algorithm is typically much faster than other ordering methods +and minimum degree ordering +algorithms that compute an exact degree \cite{GeorgeLiu89}. +Some methods, such as approximate deficiency +\cite{RothbergEisenstat98} and graph-partitioning based methods +\cite{Chaco,KarypisKumar98e,PellegriniRomanAmestoy00,schu:01} +can produce better orderings, depending on the matrix. + +The algorithm starts with an undirected graph representation of a +symmetric sparse matrix $\m{A}$. Node $i$ in the graph corresponds to row +and column $i$ of the matrix, and there is an edge $(i,j)$ in the graph if +$a_{ij}$ is nonzero. +The degree of a node is initialized to the number of off-diagonal nonzeros +in row $i$, which is the size of the set of nodes +adjacent to $i$ in the graph. + +The selection of a pivot $a_{ii}$ from the diagonal of $\m{A}$ and the first +step of Gaussian elimination corresponds to one step of graph elimination. +Numerical fill-in causes new nonzero entries in the matrix +(fill-in refers to +nonzeros in $\m{L}$ that are not in $\m{A}$). +Node $i$ is eliminated and edges are added to its neighbors +so that they form a clique (or {\em element}). To reduce fill-in, +node $i$ is selected as the node of least degree in the graph. +This process repeats until the graph is eliminated. + +The clique is represented implicitly. Rather than listing all the +new edges in the graph, a single list of nodes is kept which represents +the clique. This list corresponds to the nonzero pattern of the first +column of $\m{L}$. As the elimination proceeds, some of these cliques +become subsets of subsequent cliques, and are removed. This graph +can be stored in place, that is +using the same amount of memory as the original graph. + +The most costly part of the minimum degree algorithm is the recomputation +of the degrees of nodes adjacent to the current pivot element. +Rather than keep track of the exact degree, the approximate minimum degree +algorithm finds an upper bound on the degree that is easier to compute. +For nodes of least degree, this bound tends to be tight. Using the +approximate degree instead of the exact degree leads to a substantial savings +in run time, particularly for very irregularly structured matrices. +It has no effect on the quality of the ordering. + +In the C version of AMD, the elimination phase is followed by an +elimination tree post-ordering. This has no effect on fill-in, but +reorganizes the ordering so that the subsequent numerical factorization is +more efficient. It also includes a pre-processing phase in which nodes of +very high degree are removed (without causing fill-in), and placed last in the +permutation $\m{P}$. This reduces the run time substantially if the matrix +has a few rows with many nonzero entries, and has little effect on the quality +of the ordering. +The C version operates on the +symmetric nonzero pattern of $\m{A}+\m{A}\tr$, so it can be given +an unsymmetric matrix, or either the lower or upper triangular part of +a symmetric matrix. + +The two Fortran versions of AMD are essentially identical to two versions of +the AMD algorithm discussed in an earlier paper \cite{AmestoyDavisDuff96} +(approximate minimum external degree, both with and without aggressive +absorption). +For a discussion of the long history of the minimum degree algorithm, +see \cite{GeorgeLiu89}. + +%------------------------------------------------------------------------------ +\section{Availability} +%------------------------------------------------------------------------------ + +In addition to appearing as a Collected Algorithm of the ACM, +AMD Version 1.1 is available at http://www.cise.ufl.edu/research/sparse. +The Fortran version is available as the routine {\tt MC47} in HSL +(formerly the Harwell Subroutine Library) \cite{hsl:2002}. + +%------------------------------------------------------------------------------ +\section{Using AMD in MATLAB} +%------------------------------------------------------------------------------ + +To use AMD in MATLAB, you must first compile the AMD mexFunction. +Just type {\tt make} in the Unix system shell, while in the {\tt AMD} +directory. You can also type {\tt amd\_make} in MATLAB, while in the +{\tt AMD/MATLAB} directory. Place the {\tt AMD/MATLAB} directory in your +MATLAB path. This can be done on any system with MATLAB, including Windows. +See Section~\ref{Install} for more details on how to install AMD. + +The MATLAB statement {\tt p=amd(A)} finds a permutation vector {\tt p} such +that the Cholesky factorization {\tt chol(A(p,p))} is typically sparser than +{\tt chol(A)}. +If {\tt A} is unsymmetric, {\tt amd(A)} is identical to {\tt amd(A+A')} +(ignoring numerical cancellation). +If {\tt A} is not symmetric positive definite, +but has substantial diagonal entries and a mostly symmetric nonzero pattern, +then this ordering is also suitable for LU factorization. A partial pivoting +threshold may be required to prevent pivots from being selected off the +diagonal, such as the statement {\tt [L,U,P] = lu (A (p,p), 0.1)}. +Type {\tt help lu} for more details. +The statement {\tt [L,U,P,Q] = lu (A (p,p))} in MATLAB 6.5 is +not suitable, however, because it uses UMFPACK Version 4.0 and thus +does not attempt to select pivots from the diagonal. UMFPACK Version 4.1 +uses several strategies, including a symmetric pivoting strategy, and +will give you better results if you want to factorize an unsymmetric matrix +of this type. Refer to the UMFPACK User Guide for more details, at +http://www.cise.ufl.edu/research/sparse/umfpack. + +The AMD mexFunction is much faster than the built-in MATLAB symmetric minimum +degree ordering methods, SYMAMD and SYMMMD. Its ordering quality is +comparable to SYMAMD, and better than SYMMMD +\cite{DavisGilbertLarimoreNg00pending}. + +An optional input argument can be used to modify the control parameters for +AMD (aggressive absorption, dense row/column handling, and printing of +statistics). An optional output +argument provides statistics on the ordering, including an analysis of the +fill-in and the floating-point operation count for a subsequent factorization. +For more details (once AMD is installed), +type {\tt help amd} in the MATLAB command window. + +%------------------------------------------------------------------------------ +\section{Using AMD in a C program} +\label{Cversion} +%------------------------------------------------------------------------------ + +The C-callable AMD library consists of five user-callable routines and one +include file. There are two versions of each of the routines, with +{\tt int} and {\tt long} integers. +The routines with prefix +{\tt amd\_l\_} use {\tt long} integer arguments; the others use +{\tt int} integer arguments. If you compile AMD in the standard +ILP32 mode (32-bit {\tt int}'s, {\tt long}'s, and pointers) then the versions +are essentially identical. You will be able to solve problems using up to 2GB +of memory. If you compile AMD in the standard LP64 mode, the size of an +{\tt int} remains 32-bits, but the size of a {\tt long} and a pointer both get +promoted to 64-bits. + +The following routines are fully described in Section~\ref{Primary}: + +\begin{itemize} +\item {\tt amd\_order} +({\tt long} version: {\tt amd\_l\_order}) + {\footnotesize + \begin{verbatim} + #include "amd.h" + int n, Ap [n+1], Ai [nz], P [n] ; + double Control [AMD_CONTROL], Info [AMD_INFO] ; + int result = amd_order (n, Ap, Ai, P, Control, Info) ; + \end{verbatim} + } + Computes the approximate minimum degree ordering of an $n$-by-$n$ matrix + $\m{A}$. Returns a permutation vector {\tt P} of size {\tt n}, where + {\tt P[k] = i} if row and column {\tt i} are the {\tt k}th row and + column in the permuted matrix. + This routine allocates its own memory of size $1.2e+9n$ integers, + where $e$ is the number of nonzeros in $\m{A}+\m{A}\tr$. + It computes statistics about the matrix $\m{A}$, such as the symmetry of + its nonzero pattern, the number of nonzeros in $\m{L}$, + and the number of floating-point operations required for Cholesky and LU + factorizations (which are returned in the {\tt Info} array). + The user's input matrix is not modified. + It returns {\tt AMD\_OK} if successful, {\tt AMD\_INVALID} if + the matrix is invalid, or {\tt AMD\_OUT\_OF\_MEMORY} if out of memory. + +\item {\tt amd\_defaults} +({\tt long} version: {\tt amd\_l\_defaults}) + {\footnotesize + \begin{verbatim} + #include "amd.h" + double Control [AMD_CONTROL] ; + amd_defaults (Control) ; + \end{verbatim} + } + Sets the default control parameters in the {\tt Control} array. These can + then be modified as desired before passing the array to the other AMD + routines. + +\item {\tt amd\_control} +({\tt long} version: {\tt amd\_l\_control}) + {\footnotesize + \begin{verbatim} + #include "amd.h" + double Control [AMD_CONTROL] ; + amd_control (Control) ; + \end{verbatim} + } + Prints a description of the control parameters, and their values. + +\item {\tt amd\_info} +({\tt long} version: {\tt amd\_l\_info}) + {\footnotesize + \begin{verbatim} + #include "amd.h" + double Info [AMD_INFO] ; + amd_info (Info) ; + \end{verbatim} + } + Prints a description of the statistics computed by AMD, and their values. + +\item {\tt amd\_preprocess} +({\tt long} version: {\tt amd\_l\_info}) + {\footnotesize + \begin{verbatim} + #include "amd.h" + int n, Ap [n+1], Ai [nz], Rp [n+1], Ri [nz] ; + int result = amd_preprocess (n, Ap, Ai, Rp, Ri) ; + \end{verbatim} + } + Removes duplicate entries and sorts each column of its input $\m{A}$, + and returns the nonzero pattern of the transpose, $\m{R}=\m{A}\tr$. + It returns the transpose because this is the simplest way to sort + a matrix and remove duplicate entries. Either $\m{A}$ or $\m{A}\tr$ + can be passed to {\tt amd\_order} with little effect on the + ordering (except for minor tie-breaking changes). + +\end{itemize} + +The nonzero pattern of the matrix $\m{A}$ is represented in compressed column +form. +For an $n$-by-$n$ matrix $\m{A}$ with {\tt nz} nonzero entries, the +representation consists of two arrays: {\tt Ap} of size {\tt n+1} and {\tt Ai} +of size {\tt nz}. The row indices of entries in column {\tt j} are stored in + {\tt Ai[Ap[j]} $\ldots$ {\tt Ap[j+1]-1]}. +For {\tt amd\_order}, +no duplicate row indices may be present, and the row indices in any given +column must be sorted in ascending order. +The matrix is 0-based, and thus +row indices must be in the range {\tt 0} to {\tt n-1}. +The first entry {\tt Ap[0]} must be zero. +The total number of entries in the matrix is thus {\tt nz = Ap[n]}. + +The matrix must be square, but it does not need to be symmetric. +The {\tt amd\_order} routine constructs the nonzero pattern of +$\m{B} = \m{A}+\m{A}\tr$ (without forming $\m{A}\tr$ explicitly), +and then orders the matrix $\m{B}$. Thus, either the +lower triangular part of $\m{A}$, the upper triangular part, +or any combination may be passed. The transpose $\m{A}\tr$ may also be +passed to {\tt amd\_order}. +The diagonal entries may be present, but are ignored. + +The input to {\tt amd\_order} must have sorted columns because it uses +an in-place algorithm to construct $\m{A}+\m{A}\tr$ without first constructing +$\m{A}\tr$. This saves memory, but places an additional restriction on +the input. If the input matrix has columns with unsorted and/or duplicate +row indices, it is not valid as input to {\tt amd\_order}. To handle this +case, the {\tt amd\_preprocess} routine is provided. It sorts, transposes, +and removes duplicate entries from its input matrix, returning its result +as another compressed-column matrix $\m{R}$ which can then be passed to +{\tt amd\_order}. + +%------------------------------------------------------------------------------ +\subsection{Control parameters} +\label{control_param} +%------------------------------------------------------------------------------ + +Control parameters are set an optional {\tt Control} array. +It is optional in the sense that if +a {\tt NULL} pointer is passed for the {\tt Control} input argument, +then default control parameters are used. +% +\begin{itemize} +\item {\tt Control[AMD\_DENSE]} (or {\tt Control(1)} in MATLAB): +controls the threshold for ``dense'' +rows/columns. A dense row/column in $\m{A}+\m{A}\tr$ +can cause AMD to spend significant time +in ordering the matrix. If {\tt Control[AMD\_DENSE]} $\ge 0$, +rows/columns with +more than {\tt Control[AMD\_DENSE]} $\sqrt{n}$ entries are ignored during +the ordering, and placed last in the output order. The default +value of {\tt Control[AMD\_DENSE]} is 10. If negative, no rows/columns +are treated as ``dense.'' Rows/columns with 16 or fewer off-diagonal +entries are never considered ``dense.'' +% +\item {\tt Control[AMD\_AGGRESSIVE]} (or {\tt Control(2)} in MATLAB): +controls whether or not to use +aggressive absorption, in which a prior element is absorbed into the current +element if it is a subset of the current element, even if it is not +adjacent to the current pivot element (refer to \cite{AmestoyDavisDuff96} +for more details). The default value is nonzero, +which means that aggressive absorption will be performed. This nearly always +leads to a better ordering (because the approximate degrees are more +accurate) and a lower execution time. There are cases where it can +lead to a slightly worse ordering, however. To turn it off, set +{\tt Control[AMD\_AGGRESSIVE]} to 0. +% +\end{itemize} + +Statistics are returned in the {\tt Info} array +(if {\tt Info} is {\tt NULL}, then no statistics are returned). +Refer to {\tt amd.h} file, for more details +(14 different statistics are returned, so the list is not included here). + +%------------------------------------------------------------------------------ +\subsection{Sample C program} +%------------------------------------------------------------------------------ + +The following program, {\tt amd\_demo.c}, illustrates the basic use of AMD. +See Section~\ref{Synopsis} for a short description +of each calling sequence. + +{\footnotesize +\begin{verbatim} +#include +#include "amd.h" + +int n = 5 ; +int Ap [ ] = { 0, 2, 6, 10, 12, 14} ; +int Ai [ ] = { 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 } ; +int P [5] ; + +int main (void) +{ + int k ; + (void) amd_order (n, Ap, Ai, P, (double *) NULL, (double *) NULL) ; + for (k = 0 ; k < n ; k++) printf ("P [%d] = %d\n", k, P [k]) ; + return (0) ; +} +\end{verbatim} +} + +The {\tt Ap} and {\tt Ai} arrays represent the binary matrix +\[ +\m{A} = \left[ +\begin{array}{rrrrr} + 1 & 1 & 0 & 0 & 0 \\ + 1 & 1 & 1 & 0 & 1 \\ + 0 & 1 & 1 & 1 & 0 \\ + 0 & 0 & 1 & 1 & 0 \\ + 0 & 1 & 1 & 0 & 1 \\ +\end{array} +\right]. +\] +The diagonal entries are ignored. +% +AMD constructs the pattern of $\m{A}+\m{A}\tr$, +and returns a permutation vector of $(0, 3, 1, 4, 2)$. +% +Since the matrix is unsymmetric but with a mostly symmetric nonzero +pattern, this would be a suitable permutation for an LU factorization of a +matrix with this nonzero pattern and whose diagonal entries are not too small. +The program uses default control settings and does not return any statistics +about the ordering, factorization, or solution ({\tt Control} and {\tt Info} +are both {\tt (double *) NULL}). It also ignores the status value returned by +{\tt amd\_order}. + +More example programs are included with the AMD package. +The {\tt amd\_demo.c} program provides a more detailed demo of AMD. +Another example is the AMD mexFunction, {\tt amd\_mex.c}. + +%------------------------------------------------------------------------------ +\subsection{A note about zero-sized arrays} +%------------------------------------------------------------------------------ + +AMD uses several user-provided arrays of size {\tt n} or {\tt nz}. +Either {\tt n} or {\tt nz} can be zero. +If you attempt to {\tt malloc} an array of size zero, +however, {\tt malloc} will return a null pointer which AMD will report +as invalid. If you {\tt malloc} an array of +size {\tt n} or {\tt nz} to pass to AMD, make sure that you handle the +{\tt n} = 0 and {\tt nz = 0} cases correctly. + +%------------------------------------------------------------------------------ +\section{Synopsis of C-callable routines} +\label{Synopsis} +%------------------------------------------------------------------------------ + +The matrix $\m{A}$ is {\tt n}-by-{\tt n} with {\tt nz} entries. + +{\footnotesize +\begin{verbatim} +#include "amd.h" +int n, status, Ap [n+1], Ai [nz], P [n], Rp [n+1], Ri [nz] ; +double Control [AMD_CONTROL], Info [AMD_INFO] ; +amd_defaults (Control) ; +status = amd_order (n, Ap, Ai, P, Control, Info) ; +amd_control (Control) ; +amd_info (Info) ; +amd_preprocess (n, Ap, Ai, Rp, Ri) ; +\end{verbatim} +} + +The {\tt amd\_l\_*} routines are identical, except that all {\tt int} +arguments become {\tt long}: + +{\footnotesize +\begin{verbatim} +#include "amd.h" +long n, status, Ap [n+1], Ai [nz], P [n], Rp [n+1], Ri [nz] ; +double Control [AMD_CONTROL], Info [AMD_INFO] ; +amd_l_defaults (Control) ; +status = amd_l_order (n, Ap, Ai, P, Control, Info) ; +amd_l_control (Control) ; +amd_l_info (Info) ; +amd_l_preprocess (n, Ap, Ai, Rp, Ri) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------ +\section{Using AMD in a Fortran program} +%------------------------------------------------------------------------------ + +Two Fortran versions of AMD are provided. The {\tt AMD} routine computes the +approximate minimum degree ordering, using aggressive absorption. The +{\tt AMDBAR} routine is identical, except that it does not perform aggressive +absorption. The {\tt AMD} routine is essentially identical to the HSL +routine {\tt MC47B/BD}. +Note that earlier versions of the Fortran +{\tt AMD} and {\tt AMDBAR} routines included an {\tt IOVFLO} argument, +which is no longer present. + +In contrast to the C version, the Fortran routines require a symmetric +nonzero pattern, with no diagonal entries present although the {\tt MC47A/AD} +wrapper in HSL allows duplicates, ignores out-of-range entries, and only +uses entries from the upper triangular part of the matrix. Although we +have an experimental Fortran code for treating ``dense'' rows, the Fortran +codes in this release do not treat +``dense'' rows and columns of $\m{A}$ differently, and thus their run time +can be high if there are a few dense rows and columns in the matrix. +They do not perform a post-ordering of the elimination tree, +compute statistics on the ordering, or check the validity of their input +arguments. These facilities are provided by {\tt MC47A/AD} and other +subroutines from HSL. +Only one {\tt integer} +version of each Fortran routine is provided. +Both Fortran routines overwrite the user's input +matrix, in contrast to the C version. +% +The C version does not return the elimination or assembly tree. +The Fortran version returns an assembly tree; +refer to the User Guide for details. +The following is the syntax of the {\tt AMD} Fortran routine. +The {\tt AMDBAR} routine is identical except for the routine name. + +{\footnotesize +\begin{verbatim} + INTEGER N, IWLEN, PFREE, NCMPA, IW (IWLEN), PE (N), DEGREE (N), NV (N), + $ NEXT (N), LAST (N), HEAD (N), ELEN (N), W (N), LEN (N) + CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, + $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) + CALL AMDBAR (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, + $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) +\end{verbatim} +} + +The input matrix is provided to {\tt AMD} and {\tt AMDBAR} +in three arrays, {\tt PE}, of size {\tt N}, +{\tt LEN}, of size {\tt N}, and {\tt IW}, of size {\tt IWLEN}. The size of +{\tt IW} must be at least {\tt NZ+N}. The recommended size is +{\tt 1.2*NZ + N}. +On input, the indices of nonzero entries in row {\tt I} are stored in {\tt IW}. +{\tt PE(I)} is the index in {\tt IW} of the start of row {\tt I}. +{\tt LEN(I)} is the number of entries in row {\tt I}. +The matrix is 1-based, with row and column indices in the range 1 to {\tt N}. +Row {\tt I} is contained in +{\tt IW (PE(I)} $\ldots \:$ {\tt PE(I) + LEN(I) - 1)}. +The diagonal entries must not be present. The indices within each row must +not contain any duplicates, but they need not be sorted. The rows +themselves need not be in any particular order, and there may be empty space +between the rows. If {\tt LEN(I)} is zero, then there are no off-diagonal +entries in row {\tt I}, and {\tt PE(I)} is ignored. The integer +{\tt PFREE} defines what part of {\tt IW} contains the user's input matrix, +which is held in {\tt IW(1}~$\ldots~\:${\tt PFREE-1)}. +The contents of {\tt IW} and {\tt LEN} are undefined on output, +and {\tt PE} is modified to contain information about the ordering. + +As the algorithm proceeds, it modifies the {\tt IW} array, placing the +pattern of the partially eliminated matrix in +{\tt IW(PFREE} $\ldots \:${\tt IWLEN)}. +If this space is exhausted, the space is compressed. +The number of compressions performed on the {\tt IW} array is +returned in the scalar {\tt NCMPA}. The value of {\tt PFREE} on output is the +length of {\tt IW} required for no compressions to be needed. + +The output permutation is returned in the array {\tt LAST}, of size {\tt N}. +If {\tt I=LAST(K)}, then {\tt I} is the {\tt K}th row in the permuted +matrix. The inverse permutation is returned in the array {\tt ELEN}, where +{\tt K=ELEN(I)} if {\tt I} is the {\tt K}th row in the permuted matrix. +On output, the {\tt PE} and {\tt NV} arrays hold the assembly tree, +a supernodal elimination tree that represents the relationship between +columns of the Cholesky factor $\m{L}$. +If {\tt NV(I)} $> 0$, then {\tt I} is a node in the assembly +tree, and the parent of {\tt I} is {\tt -PE(I)}. If {\tt I} is a root of +the tree, then {\tt PE(I)} is zero. The value of {\tt NV(I)} is the +number of entries in the corresponding column of $\m{L}$, including the +diagonal. +If {\tt NV(I)} is zero, then {\tt I} is a non-principal node that is +not in the assembly tree. Node {\tt -PE(I)} is the parent of node {\tt I} +in a subtree, the root of which is a node in the assembly tree. All nodes +in one subtree belong to the same supernode in the assembly tree. +The other size {\tt N} arrays +({\tt DEGREE}, {\tt HEAD}, {\tt NEXT}, and {\tt W}) are used as workspace, +and are not defined on input or output. + +If you want to use a simpler user-interface and compute the elimination +tree post-ordering, you should be able to call the C routines {\tt amd\_order} +or {\tt amd\_l\_order} from a Fortran program. Just be sure to take into +account the 0-based indexing in the {\tt P}, {\tt Ap}, and {\tt Ai} arguments +to {\tt amd\_order} and {\tt amd\_l\_order}. A sample interface is provided +in the files {\tt AMD/Demo/amd\_f77cross.f} and +{\tt AMD/Demo/amd\_f77wrapper.c}. To compile the {\tt amd\_f77cross} program, +type {\tt make cross} in the {\tt AMD/Demo} directory. The +Fortran-to-C calling conventions are highly non-portable, so this example +is not guaranteed to work with your compiler C and Fortran compilers. +The output of {\tt amd\_f77cross} is in {\tt amd\_f77cross.out}. + +%------------------------------------------------------------------------------ +\section{Sample Fortran main program} +%------------------------------------------------------------------------------ + +The following program illustrates the basic usage of the Fortran version of AMD. +The {\tt AP} and {\tt AI} arrays represent the binary matrix +\[ +\m{A} = \left[ +\begin{array}{rrrrr} + 1 & 1 & 0 & 0 & 0 \\ + 1 & 1 & 1 & 0 & 1 \\ + 0 & 1 & 1 & 1 & 1 \\ + 0 & 0 & 1 & 1 & 0 \\ + 0 & 1 & 1 & 0 & 1 \\ +\end{array} +\right] +\] +in a conventional 1-based column-oriented form, +except that the diagonal entries are not present. +The matrix has the same as nonzero pattern of $\m{A}+\m{A}\tr$ in the C +program, in Section~\ref{Cversion}. +The output permutation is $(4, 1, 3, 5, 2)$. +It differs from the permutation returned by the C routine {\tt amd\_order} +because a post-order of the elimination tree has not yet been performed. + +{\footnotesize +\begin{verbatim} + INTEGER N, NZ, J, K, P, IWLEN, PFREE, NCMPA + PARAMETER (N = 5, NZ = 10, IWLEN = 17) + INTEGER AP (N+1), AI (NZ), LAST (N), PE (N), LEN (N), ELEN (N), + $ IW (IWLEN), DEGREE (N), NV (N), NEXT (N), HEAD (N), W (N) + DATA AP / 1, 2, 5, 8, 9, 11/ + DATA AI / 2, 1,3,5, 2,4,5, 3, 2,3 / +C load the matrix into the AMD workspace + DO 10 J = 1,N + PE (J) = AP (J) + LEN (J) = AP (J+1) - AP (J) +10 CONTINUE + DO 20 P = 1,NZ + IW (P) = AI (P) +20 CONTINUE + PFREE = NZ + 1 +C order the matrix (destroys the copy of A in IW, PE, and LEN) + CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, LAST, HEAD, + $ ELEN, DEGREE, NCMPA, W) + DO 60 K = 1, N + PRINT 50, K, LAST (K) +50 FORMAT ('P (',I2,') = ', I2) +60 CONTINUE + END +\end{verbatim} +} + +The {\tt Demo} directory contains an example of how the C version +may be called from a Fortran program, but this is highly non-portable. +For this reason, it is placed in the {\tt Demo} directory, not in the +primary {\tt Source} directory. + +%------------------------------------------------------------------------------ +\section{Installation} +\label{Install} +%------------------------------------------------------------------------------ + +The following discussion assumes you have the {\tt make} program, either in +Unix, or in Windows with Cygwin. + +System-dependent configurations are in the {\tt AMD/Make} +directory. You can edit the {\tt Make.include} +file in that directory to customize the compilation. The default +settings will work on most systems. +Sample configuration files are provided +for Linux, Sun Solaris, SGI IRIX, IBM AIX, and the DEC/Compaq Alpha. + +To compile and install the C-callable AMD library, +go to the {\tt AMD} directory and type {\tt make}. +The library will be placed in {\tt AMD/Lib/libamd.a}. +Two demo programs of the AMD ordering routine will be compiled and tested in +the {\tt AMD/Demo} directory. +The outputs of these demo programs will then be compared with output +files in the distribution. The AMD mexFunction for +use in MATLAB will also be compiled. If you do not have MATLAB +type {\tt make lib} instead. + +To compile and install the Fortran-callable AMD library, +go to the {\tt AMD} directory and type {\tt make fortran}. +The library will be placed in {\tt AMD/Lib/libamdf77.a}. +A demo program will be compiled and tested in the {\tt AMD/Demo} directory. +The output will be compared with an output file in the distribution. + +Typing {\tt make clean} will remove all but the final compiled libraries +and demo programs. Typing {\tt make purge} removes all files not in the +original distribution. +If you compile AMD and then later change the {\tt Make.include} +file or your system-specific configuration file such as {\tt Make.linux}, +then you should type {\tt make purge} and then {\tt make} to recompile. + +Here are the various parameters that you can control in your +{\tt Make.include} file: + +\begin{itemize} +\item {\tt CC = } your C compiler, such as {\tt cc}. +\item {\tt RANLIB = } your system's {\tt ranlib} program, if needed. +\item {\tt CFLAGS = } optimization flags, such as {\tt -O}. +\item {\tt LIB = } your libraries, such as {\tt -lm} or {\tt -lblas}. +\item {\tt RM =} the command to delete a file. +\item {\tt MV =} the command to rename a file. +\item {\tt MEX =} the command to compile a MATLAB mexFunction. +\item {\tt F77 =} the command to compile a Fortran program (optional). +\item {\tt F77FLAGS =} the Fortran compiler flags (optional). +\item {\tt F77LIB =} the Fortran libraries (optional). +\end{itemize} + +The {\tt Make.include} includes some definitions regarding the BLAS. +This is so that AMD and UMFPACK (which requires AMD) can share +the same configuration files. If you wish to use AMD only, then +you can ignore any references to the BLAS (the -DNBLAS compile flag). + +When you compile your program that uses the C-callable AMD library, +you need to add the {\tt AMD/Lib/libamd.a} library +and you need to tell your compiler to look in the +{\tt AMD/Include} directory for include +files. To compile a Fortran program that calls the Fortran AMD library, +you need to add the {\tt AMD/Lib/libamdf77.a} library. +See {\tt AMD/Demo/Makefile} for an example. + +If all you want to use is the AMD mexFunction in MATLAB, you can skip +the use of the {\tt make} command entirely. Simply type +{\tt amd\_make} in MATLAB while in the {\tt AMD/MATLAB} directory. +This works on any system with MATLAB, including Windows. + +If you are including AMD as a subset of a larger library and do not want +to link the C standard I/O library, or if you simply do not need to use +them, you can safely remove the {\tt amd\_control.c} and {\tt amd\_info.c} +files. Similarly, if you use default parameters (or define your +own {\tt Control} array), then you can exclude the {\tt amd\_defaults.c} +file. The {\tt amd\_preprocess.c} file is optional as well, if you +can ensure that the input matrix to {\tt amd\_order} is always sorted +and has no duplicate entries. +Each of these files contains the user-callable routines of the same +name. None of these auxiliary routines are directly called by +{\tt amd\_order}. +The {\tt amd\_dump.c} file contains debugging routines +that are neither used nor compiled unless debugging is enabled. +The {\tt amd\_internal.h} file must be edited to enable debugging; +refer to the instructions in that file. Thus, it too can be excluded +if compiled into a larger production program or library. +The bare minimum files required to use just {\tt amd\_order} are +{\tt amd.h} in the {\tt Include} directory, +and +{\tt amd\_1.c}, +{\tt amd\_2.c}, +{\tt amd\_aat.c}, +{\tt and\_order.c}, +{\tt amd\_postorder.c}, +{\tt amd\_post\_tree.c}, +{\tt amd\_valid.c}, +and +{\tt amd\_internal.h}, +in the {\tt Source} directory. + +%------------------------------------------------------------------------------ +\newpage +\section{The AMD routines} +\label{Primary} +%------------------------------------------------------------------------------ + +The file {\tt AMD/Include/amd.h} listed below +describes each user-callable routine in the C version of AMD, +and gives details on their use. + +{\footnotesize +\begin{verbatim} +/* ========================================================================= */ +/* === AMD: approximate minimum degree ordering =========================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD finds a symmetric ordering P of a matrix A so that the Cholesky + * factorization of P*A*P' has fewer nonzeros and takes less work than the + * Cholesky factorization of A. If A is not symmetric, then it performs its + * ordering on the matrix A+A'. Two sets of user-callable routines are + * provided, one for "int" integers and the other for "long" integers. + * + * The method is based on the approximate minimum degree algorithm, discussed + * in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm", + * SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp. + * 886-905, 1996. This package can perform both the AMD ordering (with + * aggressive absorption), and the AMDBAR ordering (without aggressive + * absorption) discussed in the above paper. This package differs from the + * Fortran codes discussed in the paper: + * + * (1) it can ignore "dense" rows and columns, leading to faster run times + * (2) it computes the ordering of A+A' if A is not symmetric + * (3) it is followed by a depth-first post-ordering of the assembly tree + * (or supernodal elimination tree) + * + * For historical reasons, the Fortran versions, amd.f and amdbar.f, have + * been left (nearly) unchanged. They compute the identical ordering as + * described in the above paper. + */ + +#ifndef AMD_H +#define AMD_H + +int amd_order ( /* returns 0 if OK, negative value if error */ + int n, /* A is n-by-n. n must be >= 0. */ + const int Ap [ ], /* column pointers for A, of size n+1 */ + const int Ai [ ], /* row indices of A, of size nz = Ap [n] */ + int P [ ], /* output permutation, of size n */ + double Control [ ], /* input Control settings, of size AMD_CONTROL */ + double Info [ ] /* output Info statistics, of size AMD_INFO */ +) ; + +long amd_l_order ( /* see above for description of arguments */ + long n, + const long Ap [ ], + const long Ai [ ], + long P [ ], + double Control [ ], + double Info [ ] +) ; + +/* Input arguments (not modified): + * + * n: the matrix A is n-by-n. + * Ap: an int/long array of size n+1, containing the column pointers of A. + * Ai: an int/long array of size nz, containing the row indices of A, + * where nz = Ap [n]. + * Control: a double array of size AMD_CONTROL, containing control + * parameters. Defaults are used if Control is NULL. + * + * Output arguments (not defined on input): + * + * P: an int/long array of size n, containing the output permutation. If + * row i is the kth pivot row, then P [k] = i. In MATLAB notation, + * the reordered matrix is A (P,P). + * Info: a double array of size AMD_INFO, containing statistical + * information. Ignored if Info is NULL. + * + * On input, the matrix A is stored in column-oriented form. The row indices + * of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1]. + * The row indices must appear in ascending order in each column, and there + * must not be any duplicate entries. Row indices must be in the range 0 to + * n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros + * in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n]. + * The matrix does not need to be symmetric, and the diagonal does not need to + * be present (if diagonal entries are present, they are ignored except for + * the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not + * modified. This form of the Ap and Ai arrays to represent the nonzero + * pattern of the matrix A is the same as that used internally by MATLAB. + * If you wish to use a more flexible input structure, please see the + * umfpack_*_triplet_to_col routines in the UMFPACK package, at + * http://www.cise.ufl.edu/research/sparse/umfpack, or use the amd_preprocess + * routine discussed below. + * + * Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the + * range 0 to n-1. nz = Ap [n] >= 0. For all j in the range 0 to n-1, + * and for all p in the range Ap [j] to Ap [j+1]-2, Ai [p] < Ai [p+1] must + * hold. Ai [0..nz-1] must be in the range 0 to n-1. To avoid integer + * overflow, (2.4*nz + 8*n) < INT_MAX / sizeof (int) for must hold for the + * "int" version. (2.4*nz + 8*n) < LONG_MAX / sizeof (long) must hold + * for the "long" version. Finally, Ai, Ap, and P must not be NULL. If + * any of these restrictions are not met, AMD returns AMD_INVALID. + * + * AMD returns: + * + * AMD_OK if the matrix is valid and sufficient memory can be allocated to + * perform the ordering. + * + * AMD_OUT_OF_MEMORY if not enough memory can be allocated. + * + * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is + * NULL. + * + * The AMD routine first forms the pattern of the matrix A+A', and then + * computes a fill-reducing ordering, P. If P [k] = i, then row/column i of + * the original is the kth pivotal row. In MATLAB notation, the permuted + * matrix is A (P,P), except that 0-based indexing is used instead of the + * 1-based indexing in MATLAB. + * + * The Control array is used to set various parameters for AMD. If a NULL + * pointer is passed, default values are used. The Control array is not + * modified. + * + * Control [AMD_DENSE]: controls the threshold for "dense" rows/columns. + * A dense row/column in A+A' can cause AMD to spend a lot of time in + * ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns + * with more than Control [AMD_DENSE] * sqrt (n) entries are ignored + * during the ordering, and placed last in the output order. The + * default value of Control [AMD_DENSE] is 10. If negative, no + * rows/columns are treated as "dense". Rows/columns with 16 or + * fewer off-diagonal entries are never considered "dense". + * + * Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive + * absorption, in which a prior element is absorbed into the current + * element if is a subset of the current element, even if it is not + * adjacent to the current pivot element (refer to Amestoy, Davis, + * & Duff, 1996, for more details). The default value is nonzero, + * which means to perform aggressive absorption. This nearly always + * leads to a better ordering (because the approximate degrees are + * more accurate) and a lower execution time. There are cases where + * it can lead to a slightly worse ordering, however. To turn it off, + * set Control [AMD_AGGRESSIVE] to 0. + * + * Control [2..4] are not used in the current version, but may be used in + * future versions. + * + * The Info array provides statistics about the ordering on output. If it is + * not present, the statistics are not returned. This is not an error + * condition. + * + * Info [AMD_STATUS]: the return value of AMD, either AMD_OK, + * AMD_OUT_OF_MEMORY, or AMD_INVALID. + * + * Info [AMD_N]: n, the size of the input matrix + * + * Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n] + * + * Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number + * of "matched" off-diagonal entries divided by the total number of + * off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also + * an entry, for any pair (i,j) for which i != j. In MATLAB notation, + * S = spones (A) ; + * B = tril (S, -1) + triu (S, 1) ; + * symmetry = nnz (B & B') / nnz (B) ; + * + * Info [AMD_NZDIAG]: the number of entries on the diagonal of A. + * + * Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the + * diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1) + * with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n + * (the smallest possible value). If A is perfectly unsymmetric + * (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for + * example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz + * (the largest possible value). + * + * Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were + * removed from A prior to ordering. These are placed last in the + * output order P. + * + * Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the + * current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n + * times the size of an integer. This is at most 2.4nz + 9n. This + * excludes the size of the input arguments Ai, Ap, and P, which have + * a total size of nz + 2*n + 1 integers. + * + * Info [AMD_NCMPA]: the number of garbage collections performed. + * + * Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal). + * This is a slight upper bound because mass elimination is combined + * with the approximate degree update. It is a rough upper bound if + * there are many "dense" rows/columns. The rest of the statistics, + * below, are also slight or rough upper bounds, for the same reasons. + * The post-ordering of the assembly tree might also not exactly + * correspond to a true elimination tree postordering. + * + * Info [AMD_NDIV]: the number of divide operations for a subsequent LDL' + * or LU factorization of the permuted matrix A (P,P). + * + * Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a + * subsequent LDL' factorization of A (P,P). + * + * Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a + * subsequent LU factorization of A (P,P), assuming that no numerical + * pivoting is required. + * + * Info [AMD_DMAX]: the maximum number of nonzeros in any column of L, + * including the diagonal. + * + * Info [14..19] are not used in the current version, but may be used in + * future versions. + */ + +/* ------------------------------------------------------------------------- */ +/* AMD preprocess */ +/* ------------------------------------------------------------------------- */ + +/* amd_preprocess: sorts, removes duplicate entries, and transposes the + * nonzero pattern of a column-form matrix A, to obtain the matrix R. + * + * Alternatively, you can consider this routine as constructing a row-form + * matrix from a column-form matrix. Duplicate entries are allowed in A (and + * removed in R). The columns of R are sorted. Checks its input A for errors. + * + * On input, A can have unsorted columns, and can have duplicate entries. + * Ap [0] must still be zero, and Ap must be monotonically nondecreasing. + * Row indices must be in the range 0 to n-1. + * + * On output, if this routine returns AMD_OK, then the matrix R is a valid + * input matrix for AMD_order. It has sorted columns, with no duplicate + * entries in each column. Since AMD_order operates on the matrix A+A', it + * can just as easily use A or A', so the transpose has no significant effect + * (except for minor tie-breaking, which can lead to a minor effect in the + * quality of the ordering). As an example, compare the output of amd_demo.c + * and amd_demo2.c. + * + * This routine transposes A to get R because that's the simplest way to + * sort and remove duplicate entries from a matrix. + * + * Allocates 2*n integer work arrays, and free's them when done. + * + * If you wish to call amd_order, but do not know if your matrix has unsorted + * columns or duplicate entries, then you can use the following code, which is + * fairly efficient. amd_order will not allocate any internal matrix until + * it checks that the input matrix is valid, so the method below is memory- + * efficient as well. This code snippet assumes that Rp and Ri are already + * allocated, and are the same size as Ap and Ai respectively. + + result = amd_order (n, p, Ap, Ai, Control, Info) ; + if (result == AMD_INVALID) + { + if (amd_preprocess (n, Ap, Ai, Rp, Ri) == AMD_OK) + { + result = amd_order (n, p, Rp, Ri, Control, Info) ; + } + } + + * amd_preprocess will still return AMD_INVALID if any row index in Ai is out + * of range or if the Ap array is invalid. These errors are not corrected by + * amd_preprocess since they represent a more serious error that should be + * flagged with the AMD_INVALID error code. + */ + +int amd_preprocess +( + int n, + const int Ap [ ], + const int Ai [ ], + int Rp [ ], + int Ri [ ] +) ; + +long amd_l_preprocess +( + long n, + const long Ap [ ], + const long Ai [ ], + long Rp [ ], + long Ri [ ] +) ; + +/* Input arguments (not modified): + * + * n: the matrix A is n-by-n. + * Ap: an int/long array of size n+1, containing the column pointers of A. + * Ai: an int/long array of size nz, containing the row indices of A, + * where nz = Ap [n]. + * The nonzero pattern of column j of A is in Ai [Ap [j] ... Ap [j+1]-1]. + * Ap [0] must be zero, and Ap [j] <= Ap [j+1] must hold for all j in the + * range 0 to n-1. Row indices in Ai must be in the range 0 to n-1. + * The row indices in any one column need not be sorted, and duplicates + * may exist. + * + * Output arguments (not defined on input): + * + * Rp: an int/long array of size n+1, containing the column pointers of R. + * Ri: an int/long array of size rnz, containing the row indices of R, + * where rnz = Rp [n]. Note that Rp [n] will be less than Ap [n] if + * duplicates appear in A. In general, Rp [n] <= Ap [n]. + * The data structure for R is the same as A, except that each column of + * R contains sorted row indices, and no duplicates appear in any column. + * + * amd_preprocess returns: + * + * AMD_OK if the matrix A is valid and sufficient memory can be allocated + * to perform the preprocessing. + * + * AMD_OUT_OF_MEMORY if not enough memory can be allocated. + * + * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if Rp or + * Ri are NULL. + */ + +/* ------------------------------------------------------------------------- */ +/* AMD Control and Info arrays */ +/* ------------------------------------------------------------------------- */ + +/* amd_defaults: sets the default control settings */ +void amd_defaults (double Control [ ]) ; +void amd_l_defaults (double Control [ ]) ; + +/* amd_control: prints the control settings */ +void amd_control (double Control [ ]) ; +void amd_l_control (double Control [ ]) ; + +/* amd_info: prints the statistics */ +void amd_info (double Info [ ]) ; +void amd_l_info (double Info [ ]) ; + +#define AMD_CONTROL 5 /* size of Control array */ +#define AMD_INFO 20 /* size of Info array */ + +/* contents of Control */ +#define AMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */ +#define AMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */ + +/* default Control settings */ +#define AMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */ +#define AMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */ + +/* contents of Info */ +#define AMD_STATUS 0 /* return value of amd_order and amd_l_order */ +#define AMD_N 1 /* A is n-by-n */ +#define AMD_NZ 2 /* number of nonzeros in A */ +#define AMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */ +#define AMD_NZDIAG 4 /* # of entries on diagonal */ +#define AMD_NZ_A_PLUS_AT 5 /* nz in A+A' */ +#define AMD_NDENSE 6 /* number of "dense" rows/columns in A */ +#define AMD_MEMORY 7 /* amount of memory used by AMD */ +#define AMD_NCMPA 8 /* number of garbage collections in AMD */ +#define AMD_LNZ 9 /* approx. nz in L, excluding the diagonal */ +#define AMD_NDIV 10 /* number of fl. point divides for LU and LDL' */ +#define AMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */ +#define AMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */ +#define AMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */ + +/* ------------------------------------------------------------------------- */ +/* return values of AMD */ +/* ------------------------------------------------------------------------- */ + +#define AMD_OK 0 /* success */ +#define AMD_OUT_OF_MEMORY -1 /* malloc failed */ +#define AMD_INVALID -2 /* input arguments are not valid */ + +#endif +\end{verbatim} +} + +%------------------------------------------------------------------------------ +\newpage +% References +%------------------------------------------------------------------------------ + +\bibliographystyle{plain} +\bibliography{AMD_UserGuide} + +\end{document} diff --git a/liboctave/UMFPACK/AMD/Doc/ChangeLog b/liboctave/UMFPACK/AMD/Doc/ChangeLog new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Doc/ChangeLog @@ -0,0 +1,37 @@ +Jan. 21, 2004: AMD Version 1.1 + + * No bugs found or fixed - new features added, only + * amd_preprocess added, to allow for more general input of the matrix A. + * ME=0 added to amd*.f, unused DEXT variable removed from amdbar.f, + to avoid spurious compiler warnings (this was not a bug). + * amd_demo2.c and amd_demo2.out added, to test/demo amd_preprocess. + * option to allow compile-time redefinition of malloc, free, printf added + * amd_demo.c shortened slightly (removed printing of PAP') + * User Guide modified (more details added) + * linewidth reduced from 80 to 79 columns + +Oct. 7, 2003: AMD version 1.0.1. + + * MATLAB mexFunction modified, to remove call to mexCallMATLAB function. + This function can take a long time to call, particularly if you are + ordering many small matrices. + +May 6, 2003: AMD Version 1.0 released. + + * converted to C (compare amd.f and amdbar.f with amd_2.c) + * dense rows/column removed prior to ordering + * elimination tree post-ordering added + * demos, user guide written + * statistics added (nz in L, flop count, symmetry of A) + * computes the pattern of A+A' if A is unsymmetric + * user's input matrix no longer overwritten + * degree lists initialized differently + * IOVFLO argument removed from Fortran versions (amd.f and amdbar.f) + * parameters added (dense row/column detection, aggressive absorption) + * MATLAB mexFunction added + +Jan, 1996: + + * amdbar.f posted at http://www.netlib.org (with a restricted License) + * amd.f appears as MC47B/BD in the Harwell Subroutine Library + (without the IOVFLO argument) diff --git a/liboctave/UMFPACK/AMD/Doc/License b/liboctave/UMFPACK/AMD/Doc/License new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Doc/License @@ -0,0 +1,25 @@ +AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. +Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +AMD License: + + Your use or distribution of AMD or any modified version of + AMD implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses AMD or any modified version of AMD code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: + + http://www.cise.ufl.edu/research/sparse/amd diff --git a/liboctave/UMFPACK/AMD/Doc/Makefile b/liboctave/UMFPACK/AMD/Doc/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Doc/Makefile @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# AMD Makefile for compiling on Unix systems (for GNU or original make) +#------------------------------------------------------------------------------ + +all: dist + +include ../Make/Make.include + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) *.aux *.bbl *.blg *.log *.toc + +#------------------------------------------------------------------------------ +# Create the User Guide and Quick Start Guide +#------------------------------------------------------------------------------ + +AMD_UserGuide.pdf: AMD_UserGuide.tex AMD_UserGuide.bib + pdflatex AMD_UserGuide + bibtex AMD_UserGuide + pdflatex AMD_UserGuide + pdflatex AMD_UserGuide + +dist: AMD_UserGuide.pdf + - $(RM) *.aux *.bbl *.blg *.log *.toc + diff --git a/liboctave/UMFPACK/AMD/Include/amd.h b/liboctave/UMFPACK/AMD/Include/amd.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Include/amd.h @@ -0,0 +1,359 @@ +/* ========================================================================= */ +/* === AMD: approximate minimum degree ordering =========================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD finds a symmetric ordering P of a matrix A so that the Cholesky + * factorization of P*A*P' has fewer nonzeros and takes less work than the + * Cholesky factorization of A. If A is not symmetric, then it performs its + * ordering on the matrix A+A'. Two sets of user-callable routines are + * provided, one for "int" integers and the other for "long" integers. + * + * The method is based on the approximate minimum degree algorithm, discussed + * in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm", + * SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp. + * 886-905, 1996. This package can perform both the AMD ordering (with + * aggressive absorption), and the AMDBAR ordering (without aggressive + * absorption) discussed in the above paper. This package differs from the + * Fortran codes discussed in the paper: + * + * (1) it can ignore "dense" rows and columns, leading to faster run times + * (2) it computes the ordering of A+A' if A is not symmetric + * (3) it is followed by a depth-first post-ordering of the assembly tree + * (or supernodal elimination tree) + * + * For historical reasons, the Fortran versions, amd.f and amdbar.f, have + * been left (nearly) unchanged. They compute the identical ordering as + * described in the above paper. + */ + +#ifndef AMD_H +#define AMD_H + +int amd_order ( /* returns 0 if OK, negative value if error */ + int n, /* A is n-by-n. n must be >= 0. */ + const int Ap [ ], /* column pointers for A, of size n+1 */ + const int Ai [ ], /* row indices of A, of size nz = Ap [n] */ + int P [ ], /* output permutation, of size n */ + double Control [ ], /* input Control settings, of size AMD_CONTROL */ + double Info [ ] /* output Info statistics, of size AMD_INFO */ +) ; + +long amd_l_order ( /* see above for description of arguments */ + long n, + const long Ap [ ], + const long Ai [ ], + long P [ ], + double Control [ ], + double Info [ ] +) ; + +/* Input arguments (not modified): + * + * n: the matrix A is n-by-n. + * Ap: an int/long array of size n+1, containing the column pointers of A. + * Ai: an int/long array of size nz, containing the row indices of A, + * where nz = Ap [n]. + * Control: a double array of size AMD_CONTROL, containing control + * parameters. Defaults are used if Control is NULL. + * + * Output arguments (not defined on input): + * + * P: an int/long array of size n, containing the output permutation. If + * row i is the kth pivot row, then P [k] = i. In MATLAB notation, + * the reordered matrix is A (P,P). + * Info: a double array of size AMD_INFO, containing statistical + * information. Ignored if Info is NULL. + * + * On input, the matrix A is stored in column-oriented form. The row indices + * of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1]. + * The row indices must appear in ascending order in each column, and there + * must not be any duplicate entries. Row indices must be in the range 0 to + * n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros + * in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n]. + * The matrix does not need to be symmetric, and the diagonal does not need to + * be present (if diagonal entries are present, they are ignored except for + * the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not + * modified. This form of the Ap and Ai arrays to represent the nonzero + * pattern of the matrix A is the same as that used internally by MATLAB. + * If you wish to use a more flexible input structure, please see the + * umfpack_*_triplet_to_col routines in the UMFPACK package, at + * http://www.cise.ufl.edu/research/sparse/umfpack, or use the amd_preprocess + * routine discussed below. + * + * Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the + * range 0 to n-1. nz = Ap [n] >= 0. For all j in the range 0 to n-1, + * and for all p in the range Ap [j] to Ap [j+1]-2, Ai [p] < Ai [p+1] must + * hold. Ai [0..nz-1] must be in the range 0 to n-1. To avoid integer + * overflow, (2.4*nz + 8*n) < INT_MAX / sizeof (int) for must hold for the + * "int" version. (2.4*nz + 8*n) < LONG_MAX / sizeof (long) must hold + * for the "long" version. Finally, Ai, Ap, and P must not be NULL. If + * any of these restrictions are not met, AMD returns AMD_INVALID. + * + * AMD returns: + * + * AMD_OK if the matrix is valid and sufficient memory can be allocated to + * perform the ordering. + * + * AMD_OUT_OF_MEMORY if not enough memory can be allocated. + * + * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is + * NULL. + * + * The AMD routine first forms the pattern of the matrix A+A', and then + * computes a fill-reducing ordering, P. If P [k] = i, then row/column i of + * the original is the kth pivotal row. In MATLAB notation, the permuted + * matrix is A (P,P), except that 0-based indexing is used instead of the + * 1-based indexing in MATLAB. + * + * The Control array is used to set various parameters for AMD. If a NULL + * pointer is passed, default values are used. The Control array is not + * modified. + * + * Control [AMD_DENSE]: controls the threshold for "dense" rows/columns. + * A dense row/column in A+A' can cause AMD to spend a lot of time in + * ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns + * with more than Control [AMD_DENSE] * sqrt (n) entries are ignored + * during the ordering, and placed last in the output order. The + * default value of Control [AMD_DENSE] is 10. If negative, no + * rows/columns are treated as "dense". Rows/columns with 16 or + * fewer off-diagonal entries are never considered "dense". + * + * Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive + * absorption, in which a prior element is absorbed into the current + * element if is a subset of the current element, even if it is not + * adjacent to the current pivot element (refer to Amestoy, Davis, + * & Duff, 1996, for more details). The default value is nonzero, + * which means to perform aggressive absorption. This nearly always + * leads to a better ordering (because the approximate degrees are + * more accurate) and a lower execution time. There are cases where + * it can lead to a slightly worse ordering, however. To turn it off, + * set Control [AMD_AGGRESSIVE] to 0. + * + * Control [2..4] are not used in the current version, but may be used in + * future versions. + * + * The Info array provides statistics about the ordering on output. If it is + * not present, the statistics are not returned. This is not an error + * condition. + * + * Info [AMD_STATUS]: the return value of AMD, either AMD_OK, + * AMD_OUT_OF_MEMORY, or AMD_INVALID. + * + * Info [AMD_N]: n, the size of the input matrix + * + * Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n] + * + * Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number + * of "matched" off-diagonal entries divided by the total number of + * off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also + * an entry, for any pair (i,j) for which i != j. In MATLAB notation, + * S = spones (A) ; + * B = tril (S, -1) + triu (S, 1) ; + * symmetry = nnz (B & B') / nnz (B) ; + * + * Info [AMD_NZDIAG]: the number of entries on the diagonal of A. + * + * Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the + * diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1) + * with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n + * (the smallest possible value). If A is perfectly unsymmetric + * (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for + * example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz + * (the largest possible value). + * + * Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were + * removed from A prior to ordering. These are placed last in the + * output order P. + * + * Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the + * current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n + * times the size of an integer. This is at most 2.4nz + 9n. This + * excludes the size of the input arguments Ai, Ap, and P, which have + * a total size of nz + 2*n + 1 integers. + * + * Info [AMD_NCMPA]: the number of garbage collections performed. + * + * Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal). + * This is a slight upper bound because mass elimination is combined + * with the approximate degree update. It is a rough upper bound if + * there are many "dense" rows/columns. The rest of the statistics, + * below, are also slight or rough upper bounds, for the same reasons. + * The post-ordering of the assembly tree might also not exactly + * correspond to a true elimination tree postordering. + * + * Info [AMD_NDIV]: the number of divide operations for a subsequent LDL' + * or LU factorization of the permuted matrix A (P,P). + * + * Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a + * subsequent LDL' factorization of A (P,P). + * + * Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a + * subsequent LU factorization of A (P,P), assuming that no numerical + * pivoting is required. + * + * Info [AMD_DMAX]: the maximum number of nonzeros in any column of L, + * including the diagonal. + * + * Info [14..19] are not used in the current version, but may be used in + * future versions. + */ + +/* ------------------------------------------------------------------------- */ +/* AMD preprocess */ +/* ------------------------------------------------------------------------- */ + +/* amd_preprocess: sorts, removes duplicate entries, and transposes the + * nonzero pattern of a column-form matrix A, to obtain the matrix R. + * + * Alternatively, you can consider this routine as constructing a row-form + * matrix from a column-form matrix. Duplicate entries are allowed in A (and + * removed in R). The columns of R are sorted. Checks its input A for errors. + * + * On input, A can have unsorted columns, and can have duplicate entries. + * Ap [0] must still be zero, and Ap must be monotonically nondecreasing. + * Row indices must be in the range 0 to n-1. + * + * On output, if this routine returns AMD_OK, then the matrix R is a valid + * input matrix for AMD_order. It has sorted columns, with no duplicate + * entries in each column. Since AMD_order operates on the matrix A+A', it + * can just as easily use A or A', so the transpose has no significant effect + * (except for minor tie-breaking, which can lead to a minor effect in the + * quality of the ordering). As an example, compare the output of amd_demo.c + * and amd_demo2.c. + * + * This routine transposes A to get R because that's the simplest way to + * sort and remove duplicate entries from a matrix. + * + * Allocates 2*n integer work arrays, and free's them when done. + * + * If you wish to call amd_order, but do not know if your matrix has unsorted + * columns or duplicate entries, then you can use the following code, which is + * fairly efficient. amd_order will not allocate any internal matrix until + * it checks that the input matrix is valid, so the method below is memory- + * efficient as well. This code snippet assumes that Rp and Ri are already + * allocated, and are the same size as Ap and Ai respectively. + + result = amd_order (n, p, Ap, Ai, Control, Info) ; + if (result == AMD_INVALID) + { + if (amd_preprocess (n, Ap, Ai, Rp, Ri) == AMD_OK) + { + result = amd_order (n, p, Rp, Ri, Control, Info) ; + } + } + + * amd_preprocess will still return AMD_INVALID if any row index in Ai is out + * of range or if the Ap array is invalid. These errors are not corrected by + * amd_preprocess since they represent a more serious error that should be + * flagged with the AMD_INVALID error code. + */ + +int amd_preprocess +( + int n, + const int Ap [ ], + const int Ai [ ], + int Rp [ ], + int Ri [ ] +) ; + +long amd_l_preprocess +( + long n, + const long Ap [ ], + const long Ai [ ], + long Rp [ ], + long Ri [ ] +) ; + +/* Input arguments (not modified): + * + * n: the matrix A is n-by-n. + * Ap: an int/long array of size n+1, containing the column pointers of A. + * Ai: an int/long array of size nz, containing the row indices of A, + * where nz = Ap [n]. + * The nonzero pattern of column j of A is in Ai [Ap [j] ... Ap [j+1]-1]. + * Ap [0] must be zero, and Ap [j] <= Ap [j+1] must hold for all j in the + * range 0 to n-1. Row indices in Ai must be in the range 0 to n-1. + * The row indices in any one column need not be sorted, and duplicates + * may exist. + * + * Output arguments (not defined on input): + * + * Rp: an int/long array of size n+1, containing the column pointers of R. + * Ri: an int/long array of size rnz, containing the row indices of R, + * where rnz = Rp [n]. Note that Rp [n] will be less than Ap [n] if + * duplicates appear in A. In general, Rp [n] <= Ap [n]. + * The data structure for R is the same as A, except that each column of + * R contains sorted row indices, and no duplicates appear in any column. + * + * amd_preprocess returns: + * + * AMD_OK if the matrix A is valid and sufficient memory can be allocated + * to perform the preprocessing. + * + * AMD_OUT_OF_MEMORY if not enough memory can be allocated. + * + * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if Rp or + * Ri are NULL. + */ + +/* ------------------------------------------------------------------------- */ +/* AMD Control and Info arrays */ +/* ------------------------------------------------------------------------- */ + +/* amd_defaults: sets the default control settings */ +void amd_defaults (double Control [ ]) ; +void amd_l_defaults (double Control [ ]) ; + +/* amd_control: prints the control settings */ +void amd_control (double Control [ ]) ; +void amd_l_control (double Control [ ]) ; + +/* amd_info: prints the statistics */ +void amd_info (double Info [ ]) ; +void amd_l_info (double Info [ ]) ; + +#define AMD_CONTROL 5 /* size of Control array */ +#define AMD_INFO 20 /* size of Info array */ + +/* contents of Control */ +#define AMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */ +#define AMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */ + +/* default Control settings */ +#define AMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */ +#define AMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */ + +/* contents of Info */ +#define AMD_STATUS 0 /* return value of amd_order and amd_l_order */ +#define AMD_N 1 /* A is n-by-n */ +#define AMD_NZ 2 /* number of nonzeros in A */ +#define AMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */ +#define AMD_NZDIAG 4 /* # of entries on diagonal */ +#define AMD_NZ_A_PLUS_AT 5 /* nz in A+A' */ +#define AMD_NDENSE 6 /* number of "dense" rows/columns in A */ +#define AMD_MEMORY 7 /* amount of memory used by AMD */ +#define AMD_NCMPA 8 /* number of garbage collections in AMD */ +#define AMD_LNZ 9 /* approx. nz in L, excluding the diagonal */ +#define AMD_NDIV 10 /* number of fl. point divides for LU and LDL' */ +#define AMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */ +#define AMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */ +#define AMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */ + +/* ------------------------------------------------------------------------- */ +/* return values of AMD */ +/* ------------------------------------------------------------------------- */ + +#define AMD_OK 0 /* success */ +#define AMD_OUT_OF_MEMORY -1 /* malloc failed */ +#define AMD_INVALID -2 /* input arguments are not valid */ + +#endif diff --git a/liboctave/UMFPACK/AMD/Lib/libamd.def b/liboctave/UMFPACK/AMD/Lib/libamd.def new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Lib/libamd.def @@ -0,0 +1,12 @@ +LIBRARY libamd.dll +EXPORTS +amd_order +amd_defaults +amd_control +amd_info +amd_preprocess +amd_l_order +amd_l_defaults +amd_l_control +amd_l_info +amd_l_preprocess diff --git a/liboctave/UMFPACK/AMD/MATLAB/Contents.m b/liboctave/UMFPACK/AMD/MATLAB/Contents.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/Contents.m @@ -0,0 +1,13 @@ +%Contents of the AMD sparse matrix ordering package: +% +% amd p = amd (A), the approximate minimum degree ordering of A +% amd_demo a demo of amd, using the can_24 matrix +% amd_make to comple amd for use in MATLAB +% can_24.mat a sample sparse matrix from the Harwell/Boeing collection +% +% See also: amd, colamd, symamd, colmmd, symmmd, umfpack +% +% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, +% Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +help Contents diff --git a/liboctave/UMFPACK/AMD/MATLAB/GNUmakefile b/liboctave/UMFPACK/AMD/MATLAB/GNUmakefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/GNUmakefile @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# GNUmakefile for the AMD MATLAB mexFunction +#------------------------------------------------------------------------------ + +all: amd + +include ../Make/Make.include + +MX = $(MEX) -I../Include + +AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ + amd_order amd_control amd_info amd_valid + +INC = ../Include/amd.h ../Source/amd_internal.h + +MEXAMD = $(addsuffix .o, $(subst amd_,amd_m_,$(AMD))) + +amd_m_%.o: ../Source/amd_%.c $(INC) + $(MX) -DDINT -c $< + - $(MV) amd_$*.o $@ + +amd: amd_mex.c $(MEXAMD) $(INC) + $(MX) -output amd amd_mex.c $(MEXAMD) + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) amd.mex* amd.dll diff --git a/liboctave/UMFPACK/AMD/MATLAB/Makefile b/liboctave/UMFPACK/AMD/MATLAB/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/Makefile @@ -0,0 +1,50 @@ +#------------------------------------------------------------------------------ +# compile the AMD mexFunction for MATLAB (original make only) +#------------------------------------------------------------------------------ + +# This is a very ugly Makefile, and is only provided for those who do not +# have GNU make. Note that it is not used if you have GNU make. It ignores +# dependency checking and just compiles everything. It was created +# automatically, via make -n using the GNUmakefile. That way, I don't have +# maintain two Makefiles. + +all: amd + +include ../Make/Make.include + +MX = $(MEX) -I../Include + +amd: + $(MX) -DDINT -c ../Source/amd_aat.c + $(MV) amd_aat.o amd_m_aat.o + $(MX) -DDINT -c ../Source/amd_1.c + $(MV) amd_1.o amd_m_1.o + $(MX) -DDINT -c ../Source/amd_2.c + $(MV) amd_2.o amd_m_2.o + $(MX) -DDINT -c ../Source/amd_dump.c + $(MV) amd_dump.o amd_m_dump.o + $(MX) -DDINT -c ../Source/amd_postorder.c + $(MV) amd_postorder.o amd_m_postorder.o + $(MX) -DDINT -c ../Source/amd_post_tree.c + $(MV) amd_post_tree.o amd_m_post_tree.o + $(MX) -DDINT -c ../Source/amd_defaults.c + $(MV) amd_defaults.o amd_m_defaults.o + $(MX) -DDINT -c ../Source/amd_order.c + $(MV) amd_order.o amd_m_order.o + $(MX) -DDINT -c ../Source/amd_control.c + $(MV) amd_control.o amd_m_control.o + $(MX) -DDINT -c ../Source/amd_info.c + $(MV) amd_info.o amd_m_info.o + $(MX) -DDINT -c ../Source/amd_valid.c + $(MV) amd_valid.o amd_m_valid.o + $(MX) -output amd amd_mex.c amd_m_aat.o \ + amd_m_1.o amd_m_2.o amd_m_dump.o amd_m_postorder.o \ + amd_m_post_tree.o amd_m_defaults.o amd_m_order.o amd_m_control.o \ + amd_m_info.o amd_m_valid.o + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) amd.mex* amd.dll diff --git a/liboctave/UMFPACK/AMD/MATLAB/amd.m b/liboctave/UMFPACK/AMD/MATLAB/amd.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/amd.m @@ -0,0 +1,74 @@ +function [p, Info] = amd (A, Control) +%AMD Approximate minimum degree permutation. +% P = AMD (S) returns the approximate minimum degree permutation vector for +% the sparse matrix C = S+S'. The Cholesky factorization of C (P,P), or +% S (P,P), tends to be sparser than that of C or S. AMD tends to be faster +% than SYMMMD and SYMAMD, and tends to return better orderings than SYMMMD. +% S must be square. If S is full, amd (S) is equivalent to amd (sparse (S)). +% +% Usage: P = amd (S) ; % finds the ordering +% [P, Info] = amd (S, Control) ; % optional parameters & statistics +% Control = amd ; % returns default parameters +% amd ; % prints default parameters. +% +% Control (1); If S is n-by-n, then rows/columns with more than +% max (16, (Control (1))* sqrt(n)) entries in S+S' are considered +% "dense", and ignored during ordering. They are placed last in the +% output permutation. The default is 10.0 if Control is not present. +% Control (2): If nonzero, then aggressive absorption is performed. +% This is the default if Control is not present. +% Control (3): If nonzero, print statistics about the ordering. +% +% Info (1): status (0: ok, -1: out of memory, -2: matrix invalid) +% Info (2): n = size (A,1) +% Info (3): nnz (A) +% Info (4): the symmetry of the matrix S (0.0 means purely unsymmetric, +% 1.0 means purely symmetric). Computed as: +% B = tril (S, -1) + triu (S, 1) ; symmetry = nnz (B & B') / nnz (B); +% Info (5): nnz (diag (S)) +% Info (6): nnz in S+S', excluding the diagonal (= nnz (B+B')) +% Info (7): number "dense" rows/columns in S+S' +% Info (8): the amount of memory used by AMD, in bytes +% Info (9): the number of memory compactions performed by AMD +% +% The following statistics are slight upper bounds because of the +% approximate degree in AMD. The bounds are looser if "dense" rows/columns +% are ignored during ordering (Info (7) > 0). The statistics are for a +% subsequent factorization of the matrix C (P,P). The LU factorization +% statistics assume no pivoting. +% +% Info (10): the number of nonzeros in L, excluding the diagonal +% Info (11): the number of divide operations for LL', LDL', or LU +% Info (12): the number of multiply-subtract pairs for LL' or LDL' +% Info (13): the number of multiply-subtract pairs for LU +% Info (14): the max # of nonzeros in any column of L (incl. diagonal) +% Info (15:20): unused, reserved for future use +% +% An assembly tree post-ordering is performed, which is typically the same +% as an elimination tree post-ordering. It is not always identical because +% of the approximate degree update used, and because "dense" rows/columns +% do not take part in the post-order. It well-suited for a subsequent +% "chol", however. If you require a precise elimination tree post-ordering, +% then do: +% +% P = amd (S) ; +% C = spones (S) + spones (S') ; % skip this if S already symmetric +% [ignore, Q] = sparsfun ('symetree', C (P,P)) ; +% P = P (Q) ; +% +% -------------------------------------------------------------------------- +% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, +% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. +% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. +% web: http://www.cise.ufl.edu/research/sparse/amd +% -------------------------------------------------------------------------- +% +% Acknowledgements: This work was supported by the National Science +% Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. +% +% See also COLMMD, COLAMD, COLPERM, SYMAMD, SYMMMD, SYMRCM. + +more on +help amd +more off +error ('amd mexFunction not found! Type "amd_make" in MATLAB to compile amd'); diff --git a/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m b/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m @@ -0,0 +1,96 @@ +function amd_demo +% AMD DEMO +% +% A demo of AMD for MATLAB. +% +% -------------------------------------------------------------------------- +% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, +% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. +% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. +% web: http://www.cise.ufl.edu/research/sparse/amd +% -------------------------------------------------------------------------- +% +% See also: amd, amd_make + +% This orders the same matrix as the ANSI C demo, amd_demo.c. It includes an +% additional analysis of the matrix via MATLAB's symbfact routine. + +% First, print the help information for AMD +help amd + +% Get the Harwell/Boeing can_24 matrix. This is an example matrix from the +% MATLAB-accessible UF sparse matrix collection, and can be loaded into +% MATLAB with the statment "Problem = UFget ('HB/can_24')", after obtaining +% the UFget function and its supporting routines at +% http://www.cise.ufl.edu/sparse/mat . + +load can_24 +A = Problem.A ; +n = size (A,1) ; + +figure (1) +clf +hold off +subplot (2,2,1) ; +spy (A) +% remove the "_" from the name before printing it in the plot title +title (sprintf ('%s', strrep (Problem.name, '_', '-'))) ; +fprintf ('Matrix name: %s\n', Problem.name) ; +fprintf ('Matrix title: %s\n', Problem.title) ; + +% print the details during AMD ordering and SYMBFACT +spparms ('spumoni', 1) ; + +% order the matrix. Note that the Info argument is optional. +fprintf ('\nIf the next step fails, then you have\n') ; +fprintf ('not yet compiled the AMD mexFunction.\n') ; +[p, Info] = amd (A) ; + +% order again, but this time print some statistics +[p, Info] = amd (A, [10 1 1]) ; + +fprintf ('Permutation vector:\n') ; +fprintf (' %2d', p) ; +fprintf ('\n\n') ; + +subplot (2,2,2) ; +spy (A (p,p)) +title ('Permuted matrix') ; + +% The amd_demo.c program stops here. + +fprintf ('Analyze A(p,p) with MATLAB''s symbfact routine:\n') ; +[cn, height, parent, post, R] = symbfact (A (p,p)) ; + +subplot (2,2,3) ; +spy (R') ; +title ('Cholesky factor, L') ; + +subplot (2,2,4) ; +treeplot (parent) ; +title ('elimination tree') ; + +% results from symbfact +lnz = sum (cn) ; % number of nonzeros in L, incl. diagonal +cn = cn - 1 ; % get the count of off-diagonal entries +fl = n + sum (cn.^2 + 2*cn) ; % flop count for chol (A (p,p) +fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz) ; +fprintf ('floating point operation count for chol (A (p,p)): %d\n', fl) ; + +% approximations from amd: +lnz2 = n + Info (10) ; +fl2 = n + Info (11) + 2 * Info (12) ; +fprintf ('\nResults from AMD''s approximate analysis:\n') ; +fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz2) ; +fprintf ('floating point operation count for chol (A (p,p)): %d\n\n', fl2) ; + +if (lnz2 ~= lnz | fl ~= fl2) + fprintf ('Note that the nonzero and flop counts from AMD are slight\n') ; + fprintf ('upper bounds. This is due to the approximate minimum degree\n'); + fprintf ('method used, in conjunction with "mass elimination".\n') ; + fprintf ('See the discussion about mass elimination in amd.h and\n') ; + fprintf ('amd_2.c for more details.\n') ; +end + +% turn off diagnostic output in MATLAB's sparse matrix routines +spparms ('spumoni', 0) ; diff --git a/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m.out b/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m.out @@ -0,0 +1,136 @@ +>> amd_demo + + AMD Approximate minimum degree permutation. + P = AMD (S) returns the approximate minimum degree permutation vector for + the sparse matrix C = S+S'. The Cholesky factorization of C (P,P), or + S (P,P), tends to be sparser than that of C or S. AMD tends to be faster + than SYMMMD and SYMAMD, and tends to return better orderings than SYMMMD. + S must be square. If S is full, amd (S) is equivalent to amd (sparse (S)). + + Usage: P = amd (S) ; % finds the ordering + [P, Info] = amd (S, Control) ; % optional parameters & statistics + Control = amd ; % returns default parameters + amd ; % prints default parameters. + + Control (1); If S is n-by-n, then rows/columns with more than + max (16, (Control (1))* sqrt(n)) entries in S+S' are considered + "dense", and ignored during ordering. They are placed last in the + output permutation. The default is 10.0 if Control is not present. + Control (2): If nonzero, then aggressive absorption is performed. + This is the default if Control is not present. + Control (3): If nonzero, print statistics about the ordering. + + Info (1): status (0: ok, -1: out of memory, -2: matrix invalid) + Info (2): n = size (A,1) + Info (3): nnz (A) + Info (4): the symmetry of the matrix S (0.0 means purely unsymmetric, + 1.0 means purely symmetric). Computed as: + B = tril (S, -1) + triu (S, 1) ; symmetry = nnz (B & B') / nnz (B); + Info (5): nnz (diag (S)) + Info (6): nnz in S+S', excluding the diagonal (= nnz (B+B')) + Info (7): number "dense" rows/columns in S+S' + Info (8): the amount of memory used by AMD, in bytes + Info (9): the number of memory compactions performed by AMD + + The following statistics are slight upper bounds because of the + approximate degree in AMD. The bounds are looser if "dense" rows/columns + are ignored during ordering (Info (7) > 0). The statistics are for a + subsequent factorization of the matrix C (P,P). The LU factorization + statistics assume no pivoting. + + Info (10): the number of nonzeros in L, excluding the diagonal + Info (11): the number of divide operations for LL', LDL', or LU + Info (12): the number of multiply-subtract pairs for LL' or LDL' + Info (13): the number of multiply-subtract pairs for LU + Info (14): the max # of nonzeros in any column of L (incl. diagonal) + Info (15:20): unused, reserved for future use + + An assembly tree post-ordering is performed, which is typically the same + as an elimination tree post-ordering. It is not always identical because + of the approximate degree update used, and because "dense" rows/columns + do not take part in the post-order. It well-suited for a subsequent + "chol", however. If you require a precise elimination tree post-ordering, + then do: + + P = amd (S) ; + C = spones (S) + spones (S') ; % skip this if S already symmetric + [ignore, Q] = sparsfun ('symetree', C (P,P)) ; + P = P (Q) ; + + -------------------------------------------------------------------------- + AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, + Patrick R. Amestoy, and Iain S. Duff. See ../README for License. + email: davis@cise.ufl.edu CISE Department, Univ. of Florida. + web: http://www.cise.ufl.edu/research/sparse/amd + -------------------------------------------------------------------------- + + Acknowledgements: This work was supported by the National Science + Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. + + See also COLMMD, COLAMD, COLPERM, SYMAMD, SYMMMD, SYMRCM. + +Matrix name: HB/can_24 +Matrix title: 1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. + +If the next step fails, then you have +not yet compiled the AMD mexFunction. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + + input matrix A is 24-by-24 + input matrix A has 160 nonzero entries + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 24 + nz, number of nonzeros in A: 160 + symmetry of A: 1.0000 + number of nonzeros on diagonal: 24 + nonzeros in pattern of A+A' (excl. diagonal): 136 + # dense rows/columns of A+A': 0 + memory used, in bytes: 1516 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 97 + nonzeros in L (including diagonal): 121 + # divide operations for LDL' or LU: 97 + # multiply-subtract operations for LDL': 275 + # multiply-subtract operations for LU: 453 + max nz. in any column of L (incl. diagonal): 8 + + chol flop count for real A, sqrt counted as 1 flop: 671 + LDL' flop count for real A: 647 + LDL' flop count for complex A: 3073 + LU flop count for real A (with no pivoting): 1003 + LU flop count for complex A (with no pivoting): 4497 + +Permutation vector: + 23 21 11 24 13 6 17 9 15 5 16 8 2 10 14 18 1 3 4 7 12 19 22 20 + +Analyze A(p,p) with MATLAB's symbfact routine: +predicted nonzeros: 120 +predicted flops: 656 +predicted height: 16 +predicted front size: 7 +number of nonzeros in L (including diagonal): 120 +floating point operation count for chol (A (p,p)): 656 + +Results from AMD's approximate analysis: +number of nonzeros in L (including diagonal): 121 +floating point operation count for chol (A (p,p)): 671 + +Note that the nonzero and flop counts from AMD are slight +upper bounds. This is due to the approximate minimum degree +method used, in conjunction with "mass elimination". +See the discussion about mass elimination in amd.h and +amd_2.c for more details. +>> diary off diff --git a/liboctave/UMFPACK/AMD/MATLAB/amd_make.m b/liboctave/UMFPACK/AMD/MATLAB/amd_make.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/amd_make.m @@ -0,0 +1,32 @@ +function amd_make +% AMD_MAKE: compiles the AMD mexFunction for MATLAB +% +% -------------------------------------------------------------------------- +% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, +% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. +% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. +% web: http://www.cise.ufl.edu/research/sparse/amd +% -------------------------------------------------------------------------- +% +% See also: amd, amd_demo + +help amd_make +fprintf ('Compiling the AMD mexFunction:\n') ; +cmd = sprintf ('mex -inline -O -output amd -I..%sInclude amd_mex.c', filesep) ; +files = {'amd_order', 'amd_dump', 'amd_postorder', 'amd_post_tree', ... + 'amd_aat', 'amd_2', 'amd_1', 'amd_defaults', 'amd_control', 'amd_info', ... + 'amd_valid' } ; +for i = 1 : length (files) + cmd = sprintf ('%s ..%sSource%s%s.c', cmd, filesep, filesep, files {i}) ; +end +fprintf ('%s\n', cmd) ; +try + eval (cmd) ; +catch + fprintf ('Compilation not successful.\n') ; +end + +input ('\nHit enter to run the AMD demo\n') ; +more on +amd_demo +more off diff --git a/liboctave/UMFPACK/AMD/MATLAB/amd_mex.c b/liboctave/UMFPACK/AMD/MATLAB/amd_mex.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/MATLAB/amd_mex.c @@ -0,0 +1,189 @@ +/* ========================================================================= */ +/* === AMD mexFunction ===================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* + * Usage: + * p = amd (A) + * p = amd (A, Control) + * [p, Info] = amd (A) + * [p, Info] = amd (A, Control) + * Control = amd ; % return the default Control settings for AMD + * amd ; % print the default Control settings for AMD + * + * Given a square matrix A, compute a permutation P suitable for a Cholesky + * factorization of the matrix B (P,P), where B = spones (A) + spones (A'). + * The method used is the approximate minimum degree ordering method. See + * amd.m and amd.h for more information. + */ + +#include "amd.h" +#include "mex.h" +#include "matrix.h" + +void mexFunction +( + int nlhs, + mxArray *plhs[], + int nrhs, + const mxArray *prhs[] +) +{ + int i, m, n, *Ap, *Ai, *P, nc, result, spumoni, full ; + double *Pout, *InfoOut, Control [AMD_CONTROL], Info [AMD_INFO], *ControlIn; + mxArray *A, *string, *parameter ; + + /* --------------------------------------------------------------------- */ + /* get control parameters */ + /* --------------------------------------------------------------------- */ + + spumoni = 0 ; + if (nrhs == 0) + { + /* get the default control parameters, and return */ + plhs [0] = mxCreateDoubleMatrix (AMD_CONTROL, 1, mxREAL) ; + amd_defaults (mxGetPr (plhs [0])) ; + if (nlhs == 0) + { + amd_control (mxGetPr (plhs [0])) ; + } + return ; + } + + amd_defaults (Control) ; + if (nrhs > 1) + { + ControlIn = mxGetPr (prhs [1]) ; + nc = mxGetM (prhs [1]) * mxGetN (prhs [1]) ; + Control [AMD_DENSE] + = (nc > 0) ? ControlIn [AMD_DENSE] : AMD_DEFAULT_DENSE ; + Control [AMD_AGGRESSIVE] + = (nc > 1) ? ControlIn [AMD_AGGRESSIVE] : AMD_DEFAULT_AGGRESSIVE ; + spumoni = (nc > 2) ? (ControlIn [2] != 0) : 0 ; + } + + if (spumoni > 0) + { + amd_control (Control) ; + } + + /* --------------------------------------------------------------------- */ + /* get inputs */ + /* --------------------------------------------------------------------- */ + + if (nlhs > 2 || nrhs > 2) + { + mexErrMsgTxt ("Usage: p = amd (A)\nor [p, Info] = amd (A, Control)") ; + } + + A = (mxArray *) prhs [0] ; + n = mxGetN (A) ; + m = mxGetM (A) ; + if (spumoni > 0) + { + mexPrintf (" input matrix A is %d-by-%d\n", m, n) ; + } + if (mxGetNumberOfDimensions (A) != 2) + { + mexErrMsgTxt ("amd: A must be 2-dimensional") ; + } + if (m != n) + { + mexErrMsgTxt ("amd: A must be square") ; + } + + /* --------------------------------------------------------------------- */ + /* allocate workspace for output permutation */ + /* --------------------------------------------------------------------- */ + + P = mxMalloc ((n+1) * sizeof (int)) ; + + /* --------------------------------------------------------------------- */ + /* if A is full, convert to a sparse matrix */ + /* --------------------------------------------------------------------- */ + + full = !mxIsSparse (A) ; + if (full) + { + if (spumoni > 0) + { + mexPrintf ( + " input matrix A is full (sparse copy of A will be created)\n"); + } + mexCallMATLAB (1, &A, 1, (mxArray **) prhs, "sparse") ; + } + Ap = mxGetJc (A) ; + Ai = mxGetIr (A) ; + if (spumoni > 0) + { + mexPrintf (" input matrix A has %d nonzero entries\n", Ap [n]) ; + } + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + result = amd_order (n, Ap, Ai, P, Control, Info) ; + + /* --------------------------------------------------------------------- */ + /* if A is full, free the sparse copy of A */ + /* --------------------------------------------------------------------- */ + + if (full) + { + mxDestroyArray (A) ; + } + + /* --------------------------------------------------------------------- */ + /* print results (including return value) */ + /* --------------------------------------------------------------------- */ + + if (spumoni > 0) + { + amd_info (Info) ; + } + + /* --------------------------------------------------------------------- */ + /* check error conditions */ + /* --------------------------------------------------------------------- */ + + if (result == AMD_OUT_OF_MEMORY) + { + mexErrMsgTxt ("amd: out of memory") ; + } + else if (result == AMD_INVALID) + { + mexErrMsgTxt ("amd: input matrix A is corrupted") ; + } + + /* --------------------------------------------------------------------- */ + /* copy the outputs to MATLAB */ + /* --------------------------------------------------------------------- */ + + /* output permutation, P */ + plhs [0] = mxCreateDoubleMatrix (1, n, mxREAL) ; + Pout = mxGetPr (plhs [0]) ; + for (i = 0 ; i < n ; i++) + { + Pout [i] = P [i] + 1 ; /* change to 1-based indexing for MATLAB */ + } + mxFree (P) ; + + /* Info */ + if (nlhs > 1) + { + plhs [1] = mxCreateDoubleMatrix (AMD_INFO, 1, mxREAL) ; + InfoOut = mxGetPr (plhs [1]) ; + for (i = 0 ; i < AMD_INFO ; i++) + { + InfoOut [i] = Info [i] ; + } + } +} diff --git a/liboctave/UMFPACK/AMD/MATLAB/can_24.mat b/liboctave/UMFPACK/AMD/MATLAB/can_24.mat new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a346d0d3fbdb93df3f2912c3be7c7ac2b56a8b2e GIT binary patch literal 1560 zc%03YPjAye5XGO8U+(;84B^AAyg=b22N2$O+=cTEEykZ)W$+I&$ELO@G%s+w@G}hfmHf`ccKS`@Q&V zG#=DVx7Dmx%-%Ta#nGu54eKU6|7cn#u`xAM_3E|ldd=g5w`Kl)I0za5N%pFC(Js!R9M*|=`(T&94#TRiu!u;Vc(2_Ci4HlJS>JvYd&uog%L%BorYiyy5 zHwbv`BSZ%c?9p|bhC*KZj2v-(zsQ}vPf|E~IYAUMDK%Y0G2CUr$}i>#9}xkK(rO|ph7dP#CJQnyO( zO6~?(B6(6Ex7Au%iMz5!qOC3P0NEp__9-e~_hqkn>)JlF|B}pYO&>&+$;2>Bsg_PKoJt^D}E(&rt8eRqrD$XIXTu>7ENSu?_WpZ0%}F zPG)AFc0Ts(PUYDZpGnO_@`yYp9@!x;$N_1R4tY)9O8o~iB%jD files below). + +# NOTE: -DNBLAS and other BLAS configurations are ignored by AMD, since AMD +# does not use the BLAS. This flag is here because this file, and the +# ../Make/Make.* files, are shared by UMFPACK (which requires AMD). If you +# use AMD but not UMFPACK, then you can ignore any BLAS-related configuration +# settings. + +CFLAGS = -O +RANLIB = ranlib +LIB = -lm +RM = rm -f +MV = mv -f +F77 = f77 +F77FLAGS = -O +F77LIB = +AR = ar + +#------------------------------------------------------------------------------ +# for the AMD and UMFPACK mexFunctions (-DNBLAS and -DNUTIL for UMFPACK only) +#------------------------------------------------------------------------------ + +# MATLAB 6.0 or later (default) +MEX = mex -inline -O + +# MATLAB 6.0 or later (no divide-by-zero) +# MEX = mex -inline -O -DNO_DIVIDE_BY_ZERO + +# MATLAB 5 (no BLAS, do not try to use utMalloc, utFree, and utRealloc) +# MEX = mex -inline -O -DNBLAS -DNUTIL + +#------------------------------------------------------------------------------ +# for UMFPACK only (BLAS configuration): +#------------------------------------------------------------------------------ + +# The default is to NOT use the BLAS. UMFPACK will be slow, but this is more +# portable. Try this option first, then use your architecture-specific +# configuration, below, to add the BLAS library. AMD ignores the -DNBLAS flag. + +CONFIG = -DNBLAS + +#------------------------------------------------------------------------------ +# Archicture-specific configuration (for both AMD and UMFPACK) +#------------------------------------------------------------------------------ + +# Select your architecture by un-commenting the appropriate line. The include +# file can redefine any of the above definitions, or other definitions. Use +# CC = ... to redefine the name of your C compiler, for example. Without +# any specific changes, this Makefile should work on nearly all systems. + +# include ../Make/Make.linux +# include ../Make/Make.sgi +# include ../Make/Make.solaris +# include ../Make/Make.alpha +# include ../Make/Make.rs6000 + +#------------------------------------------------------------------------------ +# remove object files and profile output +#------------------------------------------------------------------------------ + +clean: + - $(RM) *.o *.obj *.ln *.bb *.bbg *.da *.c.tcov *.c.gcov gmon.out *.bak diff --git a/liboctave/UMFPACK/AMD/Make/Make.linux b/liboctave/UMFPACK/AMD/Make/Make.linux new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Make/Make.linux @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# Linux configuration (for both AMD and UMFPACK) +#------------------------------------------------------------------------------ + +# You may also need to add -lunwind -lcprts to the LIB= string, +# if you use the Intel compiler and the Fortran BLAS. + +# Using GNU gcc and f77 compilers: + CC = gcc + CFLAGS = -O3 -fPIC + +# Using Intel's icc and ifc compilers: +# F77 = ifc +# CC = icc +# CFLAGS = -ansi -O3 -ip -tpp7 -xW -vec_report0 +# CFLAGS = -pg -g + +# Using gcc compiler with picky tests +# CC = gcc +# CFLAGS = -ansi -pedantic -W -Wall -Wno-parentheses -Wshadow -Wcast-align -Winline -Wstrict-prototypes -Wno-unknown-pragmas -O3 -fPIC + +# for gcc and gcov: +# CC = gcc +# CFLAGS = -pg -ftest-coverage -fprofile-arcs + +# Running splint +# CC = - splint +# CFLAGS = -weak -fixedformalarray -badflag -fileextensions +relaxtypes +posixlib -unrecog + +#------------------------------------------------------------------------------ +# BLAS options (for UMFPACK only) +#------------------------------------------------------------------------------ + +# 1: with no BLAS (this will be slow) +# CONFIG = -DNBLAS +# LIB = -lm + +# 2: with the ATLAS C-BLAS (http://www.netlib.org/atlas). +# CONFIG = -DCBLAS -I../ATLAS/include +# LIB = -lcblas -latlas -lm + +# 3: with Fortran interface to the ATLAS BLAS +# CONFIG = +# LIB = -lf77blas -latlas -lfrtbegin -lg2c -lm + +# 4: with Fortran interface to the BLAS, and Goto's BLAS + CONFIG = + LIB = -lgoto -lxerbla -lfrtbegin -lg2c -lm + +# 5: with Fortran interface to the BLAS, and Goto's BLAS, and no divide-by-zero +# CONFIG = -DNO_DIVIDE_BY_ZERO +# LIB = -lgoto -lxerbla -lfrtbegin -lg2c -lm diff --git a/liboctave/UMFPACK/AMD/Make/Make.rs6000 b/liboctave/UMFPACK/AMD/Make/Make.rs6000 new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Make/Make.rs6000 @@ -0,0 +1,24 @@ +#------------------------------------------------------------------------------ +# IBM RS 6000 configuration (for both AMD and UMFPACK) +#------------------------------------------------------------------------------ + +# 32-bit mode: +CFLAGS = -O4 -qipa -qmaxmem=16384 -qproto +F77FLAGS = -O4 -qipa -qmaxmem=16384 + +# 64-bit mode: +# CFLAGS = -O4 -qipa -qmaxmem=16384 -q64 -DLP64 -qproto +# F77FLAGS = -O4 -qipa -qmaxmem=16384 -q64 -DLP64 +# AR = ar -X64 + +#------------------------------------------------------------------------------ +# BLAS options (for UMFPACK only): +#------------------------------------------------------------------------------ + +# 1: with the vendor-supplied BLAS. This is the default. +CONFIG = +LIB = -lessl -lm + +# 2: with no BLAS (this will be slow) +# CONFIG = -DNBLAS +# LIB = -lm diff --git a/liboctave/UMFPACK/AMD/Make/Make.sgi b/liboctave/UMFPACK/AMD/Make/Make.sgi new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Make/Make.sgi @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# SGI IRIX configuration (for both AMD and UMFPACK) +#------------------------------------------------------------------------------ + +# Default: 32-bit mode +# CFLAGS = + +# 64-bit mode (32 bit int's and 64-bit long's): +# CFLAGS = -DLP64 -64 +# F77FLAGS = -64 + +# SGI doesn't have ranlib +RANLIB = echo + +#------------------------------------------------------------------------------ +# BLAS options (for UMFPACK only): +#------------------------------------------------------------------------------ + +# 1: Default: with 32-bit int's and long's, and the 32-bit SCSL BLAS +CONFIG = +LIB = -lscs -lm + +# 2,3: with no BLAS (32 bit or 64 bit mode) +# CONFIG = -DNBLAS +# LIB = -lm + +# 4: 64 bit mode, with 64-bit SCSL BLAS. +# CONFIG = +# LIB = -lscs_i8 -lm + +# 5: 32 bit mode, with the Fortran interface to the vendor-supplied BLAS +# CONFIG = -DNSCSL +# LIB = -lblas -lm + +# 6: 32 bit mode, with the C-BLAS interface to the vendor-supplied BLAS +# CONFIG = -DCBLAS +# LIB = -lblas -lm + diff --git a/liboctave/UMFPACK/AMD/Make/Make.solaris b/liboctave/UMFPACK/AMD/Make/Make.solaris new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Make/Make.solaris @@ -0,0 +1,34 @@ +#------------------------------------------------------------------------------ +# Sun Solaris configuration (for both AMD and UMFPACK) +#------------------------------------------------------------------------------ + +# 32-bit mode: +CC = cc +CFLAGS = -Xc -xO5 -KPIC -dalign -native +F77FLAGS = -xO5 -KPIC -dalign -native + +# 64-bit mode: +# CC = cc +# CFLAGS = -Xc -xO5 -KPIC -dalign -native -DLP64 -xtarget=ultra -xarch=v9 +# F77FLAGS = -xO5 -KPIC -dalign -native -DLP64 -xtarget=ultra -xarch=v9 + +#------------------------------------------------------------------------------ +# BLAS options (for UMFPACK only): +#------------------------------------------------------------------------------ + +# 1: Default: with the Sun Performance BLAS in 32-bit mode +CONFIG = +LIB = -lsunperf -lfai -lfsu -lfui -lsunperf -lm -lF77 -lm -lM77 -lsunmath + +# 2,3: with no BLAS (32-bit or 64-bit mode) +# CONFIG = -DNBLAS +# LIB = -lm + +# 4: the Sun Performance BLAS in 64-bit mode +# CONFIG = +# LIB = -lsunperf -lfai -lfsu -lfui -lsunperf -lm + +# 5: with the C-BLAS (http://www.netlib.org/atlas) in the ../ATLAS directory. +# CONFIG = -DCBLAS -I../ATLAS/include +# LIB = -L../ATLAS/lib/SunOS_SunUS1/ -lcblas -latlas -lm + diff --git a/liboctave/UMFPACK/AMD/Makefile b/liboctave/UMFPACK/AMD/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Makefile @@ -0,0 +1,60 @@ +#------------------------------------------------------------------------------ +# AMD Makefile (for GNU Make or original make) +#------------------------------------------------------------------------------ + +# Compile everything, including the C-callable routine and the mexFunctions. +# Do not compile the FORTRAN versions. +all: + ( cd Source ; make ) + ( cd Demo ; make ) + ( cd MATLAB ; make ) + - cat Doc/License + +# compile just the C-callable libraries and demo programs (not mexFunctions) +lib: + ( cd Source ; make ) + ( cd Demo ; make ) + - cat Doc/License + +# compile the FORTRAN libraries and demo programs (not compiled by "make all") +fortran: + ( cd Source ; make fortran ) + ( cd Demo ; make fortran ) + - cat Doc/License + +# compile a FORTRAN demo program that calls the C version of AMD +# (not compiled by "make all") +cross: + ( cd Demo ; make cross ) + - cat Doc/License + +# compile a Octave version +# (not compiled by "make all") +octave: + ( cd OCTAVE ; make ) + - cat Doc/License + +# remove object files, but keep the compiled programs and library archives +clean: + ( cd Source ; make clean ) + ( cd Demo ; make clean ) + ( cd MATLAB ; make clean ) + ( cd OCTAVE ; make clean ) + ( cd Doc ; make clean ) + +# clean, and then remove compiled programs and library archives +purge: + ( cd Source ; make purge ) + ( cd Demo ; make purge ) + ( cd MATLAB ; make purge ) + ( cd OCTAVE ; make purge ) + ( cd Doc ; make purge ) + +# create PDF documents for the original distribution +doc: + ( cd Doc ; make ) + +# get ready for distribution +dist: purge + ( cd Demo ; make dist ) + ( cd Doc ; make ) diff --git a/liboctave/UMFPACK/AMD/OCTAVE/GNUmakefile b/liboctave/UMFPACK/AMD/OCTAVE/GNUmakefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/OCTAVE/GNUmakefile @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# GNUmakefile for the AMD MATLAB mexFunction +#------------------------------------------------------------------------------ + +all: amd + +include ../Make/Make.include + +MKOCT = mkoctfile -I../Include + +OCT_SPARSE_INC = -I../../../ + +AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ + amd_order amd_control amd_info amd_valid + +INC = ../Include/amd.h ../Source/amd_internal.h + +OCTAMD = $(addsuffix .o, $(subst amd_,amd_o_,$(AMD))) + +amd_o_%.o: ../Source/amd_%.c $(INC) + $(MKOCT) -DDINT -c $< -o $@ + - $(MV) ../Source/amd_$*.o + +# Note temporary addition of octave sparse path +amd: amd.cc $(OCTAMD) $(INC) + $(MKOCT) amd.cc $(OCTAMD) $(OCT_SPARSE_INC) -o amd.oct + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) amd.oct diff --git a/liboctave/UMFPACK/AMD/OCTAVE/Makefile b/liboctave/UMFPACK/AMD/OCTAVE/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/OCTAVE/Makefile @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# compile the AMD mexFunction for MATLAB (original make only) +#------------------------------------------------------------------------------ + +# This is a very ugly Makefile, and is only provided for those who do not +# have GNU make. Note that it is not used if you have GNU make. It ignores +# dependency checking and just compiles everything. It was created +# automatically, via make -n using the GNUmakefile. That way, I don't have +# maintain two Makefiles. + +all: amd + +include ../Make/Make.include + +MKOCT = mkoctfile -I../Include + +OCT_SPARSE_INC = ../../../ + +amd: + $(MKOCT) -DDINT -o amd_o_aat.o -c ../Source/amd_aat.c + $(MKOCT) -DDINT -o amd_o_1.o -c ../Source/amd_1.c + $(MKOCT) -DDINT -o amd_o_2.o -c ../Source/amd_2.c + $(MKOCT) -DDINT -o amd_o_dump.o -c ../Source/amd_dump.c + $(MKOCT) -DDINT -o amd_o_postorder.o -c ../Source/amd_postorder.c + $(MKOCT) -DDINT -o amd_o_post_tree.o -c ../Source/amd_post_tree.c + $(MKOCT) -DDINT -o amd_o_defaults.o -c ../Source/amd_defaults.c + $(MKOCT) -DDINT -o amd_o_order.o -c ../Source/amd_order.c + $(MKOCT) -DDINT -o amd_o_control.o -c ../Source/amd_control.c + $(MKOCT) -DDINT -o amd_o_info.o -c ../Source/amd_info.c + $(MKOCT) -DDINT -o amd_o_valid.o -c ../Source/amd_valid.c + $(MKOCT) -output amd.oct amd_mex.c amd_o_aat.o \ + amd_o_1.o amd_o_2.o amd_o_dump.o amd_o_postorder.o \ + amd_o_post_tree.o amd_o_defaults.o amd_o_order.o amd_o_control.o \ + amd_o_info.o amd_o_valid.o $(OCT_SPARSE_INC) -o amd.oct + +#------------------------------------------------------------------------------ +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------ + +purge: clean + - $(RM) amd.oct diff --git a/liboctave/UMFPACK/AMD/OCTAVE/amd.cc b/liboctave/UMFPACK/AMD/OCTAVE/amd.cc new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/OCTAVE/amd.cc @@ -0,0 +1,299 @@ +/* + +Copyright (C) 2004 David Bateman + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +In addition to the terms of the GPL, you are permitted to link +this program with any Open Source program, as defined by the +Open Source Initiative (www.opensource.org) + +*/ + +/* + +This is the Octave interface to the UMFPACK AMD code, which bore the following +copyright + + AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, + Patrick R. Amestoy, and Iain S. Duff. See ../README for License. + email: davis@cise.ufl.edu CISE Department, Univ. of Florida. + web: http://www.cise.ufl.edu/research/sparse/amd + -------------------------------------------------------------------------- + + Acknowledgements: This work was supported by the National Science + Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. + +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// External AMD functions in C +extern "C" { +#include "amd.h" +} + +DEFUN_DLD (amd, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{p} =} amd (@var{s})\n\ +@deftypefnx {Loadable Function} {@var{Control} =} amd ()\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{info}] =} amd (@var{s})\n\ +\n\ +AMD Approximate minimum degree permutation. Returns the approximate\n\ +minimum degree permutation vector for the sparse matrix\n\ +@code{@var{c} = @var{S} + @var{S}'}. The Cholesky factorization of\n\ +@code{@var{c} (@var{p}, @var{p})}, or @code{@var{s} (@var{p}, @var{p})},\n\ +tends to be sparser than that of @var{c} or @var{s}.\n\ +@var{s} must be square. If @var{s} is full, @code{amd (@var{S})} is\n\ +equivalent to @code{amd (sparse (@var{s}))}.\n\ +\n\ +@table @asis\n\ +@item @var{Control} (1)\n\ +If S is n-by-n, then rows/columns with more than\n\ +@code{@dfn{max} (16, (@var{Control} (1)) * @dfn{sqrt} (@var{n}))} entries\n\ +in @code{@var{s} + @var{S}'} are considered @emph{dense}, and ignored during\n\ +ordering. They are placed last in the output permutation. The default is\n\ +10.0 if @var{Control} is not present.\n\ +@item @var{Control} (2)\n\ +If nonzero, then aggressive absorption is performed. This is the default if\n\ +@var{Control} is not present.\n\ +@item @var{Control} (3)\n\ +If nonzero, print statistics about the ordering.\n\ +@end table\n\ +\n\ +@table @asis\n\ +@item @var{Info} (1)\n\ +status (0: ok, -1: out of memory, -2: matrix invalid)\n\ +@item @var{Info} (2)\n\ +@code{@var{n} = size (@var{a}, 1)}\n\ +@item @var{Info} (3)\n\ +@code{nnz (A)}\n\ +@item @var{Info} (4)\n\ +The symmetry of the matrix @var{s} (0.0 means purely unsymmetric, 1.0 means\n\ +purely symmetric). Computed as: @code{@var{b} = tril (@var{s}, -1) +\n\ +triu (@var{s}, 1); @var{symmetry} = nnz (@var{b} & @var{b}')\n\ +/ nnz (@var{b});}\n\ +@item @var{Info} (5)\n\ +@code{nnz (diag (@var{s}))}\n\ +@item @var{Info} (6)\n\ +@dfn{nnz} in @code{@var{s} + @var{s}'}, excluding the diagonal\n\ +(= @code{nnz (@var{b} + @var{b}')})\n\ +@item @var{Info} (7)\n\ +Number of @emph{dense} rows/columns in @code{@var{s} + @var{s}'}\n\ +@item @var{Info} (8)\n\ +The amount of memory used by AMD, in bytes\n\ +@item @var{Info} (9)\n\ +The number of memory compactions performed by AMD\n\ +@end table\n\ +\n\ +The following statistics are slight upper bounds because of the\n\ +approximate degree in AMD. The bounds are looser if @emph{dense}\n\ +rows/columns are ignored during ordering @code{(@var{Info} (7) > 0)}.\n\ +The statistics are for a subsequent factorization of the matrix\n\ +@code{@var{c} (@var{p},@var{p})}. The LU factorization statistics assume\n \ +no pivoting.\n\ +\n\ +@table @asis\n\ +@item @var{Info} (10)\n\ +The number of nonzeros in L, excluding the diagonal\n\ +@item @var{Info} (11)\n\ +The number of divide operations for LL', LDL', or LU\n\ +@item @var{Info (12)}\n\ +The number of multiply-subtract pairs for LL' or LDL'\n\ +@item @var{Info} (13)\n\ +The number of multiply-subtract pairs for LU\n\ +@item @var{Info} (14)\n\ +The max number of nonzeros in any column of L (incl. diagonal)\n\ +@item @var{Info} (15:20)\n\ +unused, reserved for future use\n\ +@end table\n\ +\n\ +An assembly tree post-ordering is performed, which is typically the same\n\ +as an elimination tree post-ordering. It is not always identical because\n\ +of the approximate degree update used, and because @emph{dense} rows/columns\n\ +do not take part in the post-order. It well-suited for a subsequent\n\ +@dfn{chol}, however. If you require a precise elimination tree\n\ +post-ordering, then do:\n\ +\n\ +@group\n\ + @var{p} = @dfn{amd} (@var{s});\n\ + % skip this if S already symmetric\n\ + @var{c} = spones (@var{s}) + spones (@var{s}');\n\ + [@var{ignore}, @var{q}] = sparsfun ('symetree', @var{c} (@var{p}, @var{p}));\n\ + @var{p} = @var{p} (@var{q});\n\ +@end group\n\ +\n\ +AMD Version 1.1 (Jan. 21, 2004), Copyright @copyright{} 2004 by\n\ +Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff.\n\ +\n\ +email: davis@@cise.ufl.edu (CISE Department, Univ. of Florida).\n\ +\n\ +web: http://www.cise.ufl.edu/research/sparse/amd\n\ +\n\ +Acknowledgements: This work was supported by the National Science\n\ +Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270.\n\ +@end deftypefn") +{ + int nargin = args.length (); + octave_value_list retval; + int spumoni = 0; + + if (nargin > 2 || nargout > 2) + usage ("p = amd (A) or [p, Info] = amd (A, Control)"); + else if (nargin == 0) + { + // Get the default control parameter, and return + NDArray control (dim_vector (AMD_CONTROL, 1)); + double *control_ptr = control.fortran_vec (); + amd_defaults (control_ptr); + if (nargout == 0) + amd_control (control_ptr); + else + retval(0) = control; + } + else + { + NDArray control (dim_vector (AMD_CONTROL, 1)); + double *control_ptr = control.fortran_vec (); + amd_defaults (control_ptr); + + if (nargin > 1) + { + NDArray control_in = args(1).array_value(); + + if (error_state) + { + error ("amd: could not read control vector"); + return retval; + } + + dim_vector dv = control_in.dims (); + if (dv.length() > 2 || (dv(0) != 1 && dv(1) != 1)) + { + error ("amd: control vector isn't a vector"); + return retval; + } + + int nc = dv.numel (); + control (AMD_DENSE) = (nc > 0 ? control_in (AMD_DENSE) : + AMD_DEFAULT_DENSE); + control (AMD_AGGRESSIVE) = (nc > 1 ? control_in (AMD_AGGRESSIVE) : + AMD_DEFAULT_AGGRESSIVE); + spumoni = (nc > 2 ? (control_in (2) != 0) : 0); + } + + if (spumoni > 0) + amd_control (control_ptr); + + int *Ap, *Ai; + int n, m, nz; + + // These are here only so that the C++ destructors don't prematurally + // remove the underlying data we are interested in + SparseMatrix sm; + SparseComplexMatrix scm; + Matrix mm; + ComplexMatrix cm; + + if (args(0).class_name () != "sparse" && spumoni > 0) + octave_stdout << " input matrix A is full (sparse copy" + << " of A will be created)" << std::endl; + + if (args(0).is_complex_type ()) + { + scm = args(0).sparse_complex_matrix_value (); + Ai = scm.ridx (); + Ap = scm.cidx (); + m = scm.rows (); + n = scm.cols (); + nz = scm.nnz (); + } + else + { + sm = args(0).sparse_matrix_value (); + Ai = sm.ridx (); + Ap = sm.cidx (); + m = sm.rows (); + n = sm.cols (); + nz = sm.nnz (); + } + + if (spumoni > 0) + octave_stdout << " input matrix A is " << m << "-by-" << n + << std::endl; + + if (m != n) + { + error ("amd: A must be square"); + return retval; + } + + if (spumoni > 0) + octave_stdout << " input matrix A has " << nz << + " nonzero entries" << std::endl; + + // allocate workspace for output permutation + Array P(n+1); + int *P_ptr = P.fortran_vec (); + NDArray info (dim_vector (AMD_INFO, 1)); + double *info_ptr = info.fortran_vec (); + int result; + + // order the matrix + result = amd_order (n, Ap, Ai, P_ptr, control_ptr, info_ptr); + + // print results (including return value) + if (spumoni > 0) + amd_info (info_ptr); + + // check error conditions + if (result == AMD_OUT_OF_MEMORY) + error ("amd: out of memory"); + else if (result == AMD_INVALID) + error ("amd: input matrix A is corrupted"); + else + { + // copy the outputs to Octave + + // output permutation, P + NDArray perm (dim_vector (1, n)); + for (int i = 0; i < n; i++) + perm (i) = double (P(i) + 1); // 1-based indexing for Octave + + retval (0) = perm; + + // Info + if (nargout > 1) + retval (1) = info; + } + } + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m b/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m @@ -0,0 +1,61 @@ +function amd_demo +% AMD DEMO +% +% A demo of AMD for OCTAVE. +% +% -------------------------------------------------------------------------- +% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, +% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. +% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. +% web: http://www.cise.ufl.edu/research/sparse/amd +% -------------------------------------------------------------------------- +% +% See also: amd + +% Get the Harwell/Boeing can_24 matrix. This is an example matrix from the +% MATLAB-accessible UF sparse matrix collection, and can be loaded into +% MATLAB with the statment "Problem = UFget ('HB/can_24')", after obtaining +% the UFget function and its supporting routines at +% http://www.cise.ufl.edu/sparse/mat . + +load can_24.mat +A = Problem.A ; +n = size (A,1) ; + +figure (1) +clf +hold off +subplot (2,1,1) ; +% remove the "_" from the name before printing it in the plot title +title (sprintf ('%s', strrep (Problem.name, '_', '-'))) ; +fprintf ('Matrix name: %s\n', Problem.name) ; +fprintf ('Matrix title: %s\n', Problem.title) ; +spy (A) + +% print the details during AMD ordering and SYMBFACT +control = amd (); +control (3) = 1; + +% order the matrix. Note that the Info argument is optional. +fprintf ('\nIf the next step fails, then you have\n') ; +fprintf ('not yet compiled the AMD mexFunction.\n') ; +[p, Info] = amd (A, control) ; + +% order again, but this time print some statistics +[p, Info] = amd (A, [10 1 1]) ; + +fprintf ('Permutation vector:\n') ; +fprintf (' %2d', p) ; +fprintf ('\n\n') ; + +subplot (2,1,2) ; +title ('Permuted matrix') ; +spy (A (p,p)) + +% approximations from amd: +lnz2 = n + Info (10) ; +fl2 = n + Info (11) + 2 * Info (12) ; +fprintf ('\nResults from AMD''s approximate analysis:\n') ; +fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz2) ; +fprintf ('floating point operation count for chol (A (p,p)): %d\n\n', fl2) ; + diff --git a/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m.out b/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m.out @@ -0,0 +1,20 @@ +octave:3> amd_demo +ans = 1 +Matrix name: HB/can_24 +Matrix title: 1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. + +If the next step fails, then you have +not yet compiled the AMD mexFunction. + input matrix A is 24-by-24 + input matrix A has 160 nonzero entries + input matrix A is 24-by-24 + input matrix A has 160 nonzero entries +Permutation vector: + 23 21 11 24 13 6 17 9 15 5 16 8 2 10 14 18 1 3 4 7 12 19 22 20 + + +Results from AMD's approximate analysis: +number of nonzeros in L (including diagonal): 121 +floating point operation count for chol (A (p,p)): 671 + +octave:4> quit diff --git a/liboctave/UMFPACK/AMD/OCTAVE/can_24.mat b/liboctave/UMFPACK/AMD/OCTAVE/can_24.mat new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d0b9df09f2ad7bc03642d76256ef513af40583be GIT binary patch literal 2243 zc%1E)O;5r=5QYm1$cHGXXyT=wyntF`j2w)qq(lrYq(GtHoXFb{#rP7pAk|ed=yQ`r+lIZc1_!)cdL*JXh zzZg&_fq4qtTkhDFN0#Rfp1*zHUxSnQlqOFaEPxfT4mQ9h*a1~=2dieQQLCCzh83&ry+C(ia|!7|G&0h*IuLxySRwPu+= z&1z6=@ed6W>yZ%pE3ED2|k7S1CqC&}VsOq@9r@Rfw~;d`?oIq|?c_ 0 */ + const Int Ap [ ], /* input of size n+1, not modified */ + const Int Ai [ ], /* input of size nz = Ap [n], not modified */ + Int P [ ], /* size n output permutation */ + Int Pinv [ ], /* size n output inverse permutation */ + Int Len [ ], /* size n input, undefined on output */ + Int slen, /* slen >= sum (Len [0..n-1]) + 7n, + * ideally slen = 1.2 * sum (Len) + 8n */ + Int S [ ], /* size slen workspace */ + double Control [ ], /* input array of size AMD_CONTROL */ + double Info [ ] /* output array of size AMD_INFO */ +) +{ + Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, + *Elen, *Degree, *s, *W, *Sp, *Tp ; + + /* --------------------------------------------------------------------- */ + /* construct the matrix for AMD_2 */ + /* --------------------------------------------------------------------- */ + + ASSERT (n > 0) ; + + iwlen = slen - 6*n ; + s = S ; + Pe = s ; s += n ; + Nv = s ; s += n ; + Head = s ; s += n ; + Elen = s ; s += n ; + Degree = s ; s += n ; + W = s ; s += n ; + Iw = s ; s += iwlen ; + + ASSERT (AMD_valid (n, n, Ap, Ai)) ; + + /* construct the pointers for A+A' */ + Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */ + Tp = W ; + pfree = 0 ; + for (j = 0 ; j < n ; j++) + { + Pe [j] = pfree ; + Sp [j] = pfree ; + pfree += Len [j] ; + } + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is strictly required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be very slow. For better performance, at + * least size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + +#ifndef NDEBUG + for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ; +#endif + + for (k = 0 ; k < n ; k++) + { + AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ; + p1 = Ap [k] ; + p2 = Ap [k+1] ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + ASSERT (j >= 0 && j < n) ; + if (j < k) + { + /* entry A (j,k) in the strictly upper triangular part */ + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ; + Iw [Sp [j]++] = k ; + Iw [Sp [k]++] = j ; + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + } + } + +#ifndef NDEBUG + for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ; + ASSERT (Sp [n-1] == pfree) ; +#endif + + /* Tp and Sp no longer needed ] */ + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_2 (n, Pe, Iw, Len, iwlen, pfree, + Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ; +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_2.c b/liboctave/UMFPACK/AMD/Source/amd_2.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_2.c @@ -0,0 +1,1823 @@ +/* ========================================================================= */ +/* === AMD_2 =============================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_2: performs the AMD ordering on a symmetric sparse matrix A, followed + * by a postordering (via depth-first search) of the assembly tree using the + * AMD_postorder routine. + */ + +#include "amd_internal.h" + +GLOBAL void AMD_2 +( + Int n, /* A is n-by-n, where n > 0 */ + Int Pe [ ], /* Pe [0..n-1]: index in Iw of row i on input */ + Int Iw [ ], /* workspace of size iwlen. Iw [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* Len [0..n-1]: length for row/column i on input */ + Int iwlen, /* length of Iw. iwlen >= pfree + n */ + Int pfree, /* Iw [pfree ... iwlen-1] is empty on input */ + + /* 7 size-n workspaces, not defined on input: */ + Int Nv [ ], /* the size of each supernode on output */ + Int Next [ ], /* the output inverse permutation */ + Int Last [ ], /* the output permutation */ + Int Head [ ], + Int Elen [ ], /* the size columns of L for each supernode */ + Int Degree [ ], + Int W [ ], + + /* control parameters and output statistics */ + double Control [ ], /* array of size AMD_CONTROL */ + double Info [ ] /* array of size AMD_INFO */ +) +{ + +/* + * Given a representation of the nonzero pattern of a symmetric matrix, A, + * (excluding the diagonal) perform an approximate minimum (UMFPACK/MA38-style) + * degree ordering to compute a pivot order such that the introduction of + * nonzeros (fill-in) in the Cholesky factors A = LL' is kept low. At each + * step, the pivot selected is the one with the minimum UMFAPACK/MA38-style + * upper-bound on the external degree. This routine can optionally perform + * aggresive absorption (as done by MC47B in the Harwell Subroutine + * Library). + * + * The approximate degree algorithm implemented here is the symmetric analog of + * the degree update algorithm in MA38 and UMFPACK (the Unsymmetric-pattern + * MultiFrontal PACKage, both by Davis and Duff). The routine is based on the + * MA27 minimum degree ordering algorithm by Iain Duff and John Reid. + * + * This routine is a translation of the original AMDBAR and MC47B routines, + * in Fortran, with the following modifications: + * + * (1) dense rows/columns are removed prior to ordering the matrix, and placed + * last in the output order. The presence of a dense row/column can + * increase the ordering time by up to O(n^2), unless they are removed + * prior to ordering. + * + * (2) the minimum degree ordering is followed by a postordering (depth-first + * search) of the assembly tree. Note that mass elimination (discussed + * below) combined with the approximate degree update can lead to the mass + * elimination of nodes with lower exact degree than the current pivot + * element. No additional fill-in is caused in the representation of the + * Schur complement. The mass-eliminated nodes merge with the current + * pivot element. They are ordered prior to the current pivot element. + * Because they can have lower exact degree than the current element, the + * merger of two or more of these nodes in the current pivot element can + * lead to a single element that is not a "fundamental supernode". The + * diagonal block can have zeros in it. Thus, the assembly tree used here + * is not guaranteed to be the precise supernodal elemination tree (with + * "funadmental" supernodes), and the postordering performed by this + * routine is not guaranteed to be a precise postordering of the + * elimination tree. + * + * (3) input parameters are added, to control aggressive absorption and the + * detection of "dense" rows/columns of A. + * + * (4) additional statistical information is returned, such as the number of + * nonzeros in L, and the flop counts for subsequent LDL' and LU + * factorizations. These are slight upper bounds, because of the mass + * elimination issue discussed above. + * + * (5) additional routines are added to interface this routine to MATLAB + * to provide a simple C-callable user-interface, to check inputs for + * errors, compute the symmetry of the pattern of A and the number of + * nonzeros in each row/column of A+A', to compute the pattern of A+A', + * to perform the assembly tree postordering, and to provide debugging + * ouput. Many of these functions are also provided by the Fortran + * Harwell Subroutine Library routine MC47A. + * + * (6) both "int" and "long" versions are provided. In the descriptions below + * and integer is and "int" or "long", depending on which version is + * being used. + + ********************************************************************** + ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** + ********************************************************************** + ** If you want error checking, a more versatile input format, and a ** + ** simpler user interface, use amd_order or amd_l_order instead. ** + ** This routine is not meant to be user-callable. ** + ********************************************************************** + + * ---------------------------------------------------------------------------- + * References: + * ---------------------------------------------------------------------------- + * + * [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern multifrontal + * method for sparse LU factorization", SIAM J. Matrix Analysis and + * Applications, vol. 18, no. 1, pp. 140-158. Discusses UMFPACK / MA38, + * which first introduced the approximate minimum degree used by this + * routine. + * + * [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An approximate + * minimum degree ordering algorithm," SIAM J. Matrix Analysis and + * Applications, vol. 17, no. 4, pp. 886-905, 1996. Discusses AMDBAR and + * MC47B, which are the Fortran versions of this routine. + * + * [3] Alan George and Joseph Liu, "The evolution of the minimum degree + * ordering algorithm," SIAM Review, vol. 31, no. 1, pp. 1-19, 1989. + * We list below the features mentioned in that paper that this code + * includes: + * + * mass elimination: + * Yes. MA27 relied on supervariable detection for mass elimination. + * + * indistinguishable nodes: + * Yes (we call these "supervariables"). This was also in the MA27 + * code - although we modified the method of detecting them (the + * previous hash was the true degree, which we no longer keep track + * of). A supervariable is a set of rows with identical nonzero + * pattern. All variables in a supervariable are eliminated together. + * Each supervariable has as its numerical name that of one of its + * variables (its principal variable). + * + * quotient graph representation: + * Yes. We use the term "element" for the cliques formed during + * elimination. This was also in the MA27 code. The algorithm can + * operate in place, but it will work more efficiently if given some + * "elbow room." + * + * element absorption: + * Yes. This was also in the MA27 code. + * + * external degree: + * Yes. The MA27 code was based on the true degree. + * + * incomplete degree update and multiple elimination: + * No. This was not in MA27, either. Our method of degree update + * within MC47B is element-based, not variable-based. It is thus + * not well-suited for use with incomplete degree update or multiple + * elimination. + * + * Authors, and Copyright (C) 2004 by: + * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. + * + * Acknowledgements: This work (and the UMFPACK package) was supported by the + * National Science Foundation (ASC-9111263, DMS-9223088, and CCR-0203270). + * The UMFPACK/MA38 approximate degree update algorithm, the unsymmetric analog + * which forms the basis of AMD, was developed while Tim Davis was supported by + * CERFACS (Toulouse, France) in a post-doctoral position. This C version, and + * the etree postorder, were written while Tim Davis was on sabbatical at + * Stanford University and Lawrence Berkeley National Laboratory. + + * ---------------------------------------------------------------------------- + * INPUT ARGUMENTS (unaltered): + * ---------------------------------------------------------------------------- + + * n: The matrix order. Restriction: n >= 1. + * + * iwlen: The size of the Iw array. On input, the matrix is stored in + * Iw [0..pfree-1]. However, Iw [0..iwlen-1] should be slightly larger + * than what is required to hold the matrix, at least iwlen >= pfree + n. + * Otherwise, excessive compressions will take place. The recommended + * value of iwlen is 1.2 * pfree + n, which is the value used in the + * user-callable interface to this routine (amd_order.c). The algorithm + * will not run at all if iwlen < pfree. Restriction: iwlen >= pfree + n. + * Note that this is slightly more restrictive than the actual minimum + * (iwlen >= pfree), but AMD_2 will be very slow with no elbow room. + * Thus, this routine enforces a bare minimum elbow room of size n. + * + * pfree: On input the tail end of the array, Iw [pfree..iwlen-1], is empty, + * and the matrix is stored in Iw [0..pfree-1]. During execution, + * additional data is placed in Iw, and pfree is modified so that + * Iw [pfree..iwlen-1] is always the unused part of Iw. + * + * Control: A double array of size AMD_CONTROL containing input parameters + * that affect how the ordering is computed. If NULL, then default + * settings are used. + * + * Control [AMD_DENSE] is used to determine whether or not a given input + * row is "dense". A row is "dense" if the number of entries in the row + * exceeds Control [AMD_DENSE] times sqrt (n), except that rows with 16 or + * fewer entries are never considered "dense". To turn off the detection + * of dense rows, set Control [AMD_DENSE] to a negative number, or to a + * number larger than sqrt (n). The default value of Control [AMD_DENSE] + * is AMD_DEFAULT_DENSE, which is defined in amd.h as 10. + * + * Control [AMD_AGGRESSIVE] is used to determine whether or not aggressive + * absorption is to be performed. If nonzero, then aggressive absorption + * is performed (this is the default). + + * ---------------------------------------------------------------------------- + * INPUT/OUPUT ARGUMENTS: + * ---------------------------------------------------------------------------- + * + * Pe: An integer array of size n. On input, Pe [i] is the index in Iw of + * the start of row i. Pe [i] is ignored if row i has no off-diagonal + * entries. Thus Pe [i] must be in the range 0 to pfree-1 for non-empty + * rows. + * + * During execution, it is used for both supervariables and elements: + * + * Principal supervariable i: index into Iw of the description of + * supervariable i. A supervariable represents one or more rows of + * the matrix with identical nonzero pattern. In this case, + * Pe [i] >= 0. + * + * Non-principal supervariable i: if i has been absorbed into another + * supervariable j, then Pe [i] = FLIP (j), where FLIP (j) is defined + * as (-(j)-2). Row j has the same pattern as row i. Note that j + * might later be absorbed into another supervariable j2, in which + * case Pe [i] is still FLIP (j), and Pe [j] = FLIP (j2) which is + * < EMPTY, where EMPTY is defined as (-1) in amd_internal.h. + * + * Unabsorbed element e: the index into Iw of the description of element + * e, if e has not yet been absorbed by a subsequent element. Element + * e is created when the supervariable of the same name is selected as + * the pivot. In this case, Pe [i] >= 0. + * + * Absorbed element e: if element e is absorbed into element e2, then + * Pe [e] = FLIP (e2). This occurs when the pattern of e (which we + * refer to as Le) is found to be a subset of the pattern of e2 (that + * is, Le2). In this case, Pe [i] < EMPTY. If element e is "null" + * (it has no nonzeros outside its pivot block), then Pe [e] = EMPTY, + * and e is the root of an assembly subtree (or the whole tree if + * there is just one such root). + * + * Dense variable i: if i is "dense", then Pe [i] = EMPTY. + * + * On output, Pe holds the assembly tree/forest, which implicitly + * represents a pivot order with identical fill-in as the actual order + * (via a depth-first search of the tree), as follows. If Nv [i] > 0, + * then i represents a node in the assembly tree, and the parent of i is + * Pe [i], or EMPTY if i is a root. If Nv [i] = 0, then (i, Pe [i]) + * represents an edge in a subtree, the root of which is a node in the + * assembly tree. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Info: A double array of size AMD_INFO. If present, (that is, not NULL), + * then statistics about the ordering are returned in the Info array. + * See amd.h for a description. + + * ---------------------------------------------------------------------------- + * INPUT/MODIFIED (undefined on output): + * ---------------------------------------------------------------------------- + * + * Len: An integer array of size n. On input, Len [i] holds the number of + * entries in row i of the matrix, excluding the diagonal. The contents + * of Len are undefined on output. + * + * Iw: An integer array of size iwlen. On input, Iw [0..pfree-1] holds the + * description of each row i in the matrix. The matrix must be symmetric, + * and both upper and lower triangular parts must be present. The + * diagonal must not be present. Row i is held as follows: + * + * Len [i]: the length of the row i data structure in the Iw array. + * Iw [Pe [i] ... Pe [i] + Len [i] - 1]: + * the list of column indices for nonzeros in row i (simple + * supervariables), excluding the diagonal. All supervariables + * start with one row/column each (supervariable i is just row i). + * If Len [i] is zero on input, then Pe [i] is ignored on input. + * + * Note that the rows need not be in any particular order, and there + * may be empty space between the rows. + * + * During execution, the supervariable i experiences fill-in. This is + * represented by placing in i a list of the elements that cause fill-in + * in supervariable i: + * + * Len [i]: the length of supervariable i in the Iw array. + * Iw [Pe [i] ... Pe [i] + Elen [i] - 1]: + * the list of elements that contain i. This list is kept short + * by removing absorbed elements. + * Iw [Pe [i] + Elen [i] ... Pe [i] + Len [i] - 1]: + * the list of supervariables in i. This list is kept short by + * removing nonprincipal variables, and any entry j that is also + * contained in at least one of the elements (j in Le) in the list + * for i (e in row i). + * + * When supervariable i is selected as pivot, we create an element e of + * the same name (e=i): + * + * Len [e]: the length of element e in the Iw array. + * Iw [Pe [e] ... Pe [e] + Len [e] - 1]: + * the list of supervariables in element e. + * + * An element represents the fill-in that occurs when supervariable i is + * selected as pivot (which represents the selection of row i and all + * non-principal variables whose principal variable is i). We use the + * term Le to denote the set of all supervariables in element e. Absorbed + * supervariables and elements are pruned from these lists when + * computationally convenient. + * + * CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. + * The contents of Iw are undefined on output. + + * ---------------------------------------------------------------------------- + * OUTPUT (need not be set on input): + * ---------------------------------------------------------------------------- + * + * Nv: An integer array of size n. During execution, ABS (Nv [i]) is equal to + * the number of rows that are represented by the principal supervariable + * i. If i is a nonprincipal or dense variable, then Nv [i] = 0. + * Initially, Nv [i] = 1 for all i. Nv [i] < 0 signifies that i is a + * principal variable in the pattern Lme of the current pivot element me. + * After element me is constructed, Nv [i] is set back to a positive + * value. + * + * On output, Nv [i] holds the number of pivots represented by super + * row/column i of the original matrix, or Nv [i] = 0 for non-principal + * rows/columns. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Elen: An integer array of size n. See the description of Iw above. At the + * start of execution, Elen [i] is set to zero for all rows i. During + * execution, Elen [i] is the number of elements in the list for + * supervariable i. When e becomes an element, Elen [e] = FLIP (esize) is + * set, where esize is the size of the element (the number of pivots, plus + * the number of nonpivotal entries). Thus Elen [e] < EMPTY. + * Elen (i) = EMPTY set when variable i becomes nonprincipal. + * + * For variables, Elen (i) >= EMPTY holds until just before the + * postordering and permutation vectors are computed. For elements, + * Elen [e] < EMPTY holds. + * + * On output, Elen [i] is the degree of the row/column in the Cholesky + * factorization of the permuted matrix, corresponding to the original row + * i, if i is a super row/column. It is equal to EMPTY if i is + * non-principal. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Note that the contents of Elen on output differ from the Fortran + * version (Elen holds the inverse permutation in the Fortran version, + * which is instead returned in the Next array in this C version, + * described below). + * + * Last: In a degree list, Last [i] is the supervariable preceding i, or EMPTY + * if i is the head of the list. In a hash bucket, Last [i] is the hash + * key for i. + * + * Last [Head [hash]] is also used as the head of a hash bucket if + * Head [hash] contains a degree list (see the description of Head, + * below). + * + * On output, Last [0..n-1] holds the permutation. That is, if + * i = Last [k], then row i is the kth pivot row (where k ranges from 0 to + * n-1). Row Last [k] of A is the kth row in the permuted matrix, PAP'. + * + * Next: Next [i] is the supervariable following i in a link list, or EMPTY if + * i is the last in the list. Used for two kinds of lists: degree lists + * and hash buckets (a supervariable can be in only one kind of list at a + * time). + * + * On output Next [0..n-1] holds the inverse permutation. That is, if + * k = Next [i], then row i is the kth pivot row. Row i of A appears as + * the (Next[i])-th row in the permuted matrix, PAP'. + * + * Note that the contents of Next on output differ from the Fortran + * version (Next is undefined on output in the Fortran version). + + * ---------------------------------------------------------------------------- + * LOCAL WORKSPACE (not input or output - used only during execution): + * ---------------------------------------------------------------------------- + * + * Degree: An integer array of size n. If i is a supervariable, then + * Degree [i] holds the current approximation of the external degree of + * row i (an upper bound). The external degree is the number of nonzeros + * in row i, minus ABS (Nv [i]), the diagonal part. The bound is equal to + * the exact external degree if Elen [i] is less than or equal to two. + * + * We also use the term "external degree" for elements e to refer to + * |Le \ Lme|. If e is an element, then Degree [e] is |Le|, which is the + * degree of the off-diagonal part of the element e (not including the + * diagonal part). + * + * Head: An integer array of size n. Head is used for degree lists. + * Head [deg] is the first supervariable in a degree list. All + * supervariables i in a degree list Head [deg] have the same approximate + * degree, namely, deg = Degree [i]. If the list Head [deg] is empty then + * Head [deg] = EMPTY. + * + * During supervariable detection Head [hash] also serves as a pointer to + * a hash bucket. If Head [hash] >= 0, there is a degree list of degree + * hash. The hash bucket head pointer is Last [Head [hash]]. If + * Head [hash] = EMPTY, then the degree list and hash bucket are both + * empty. If Head [hash] < EMPTY, then the degree list is empty, and + * FLIP (Head [hash]) is the head of the hash bucket. After supervariable + * detection is complete, all hash buckets are empty, and the + * (Last [Head [hash]] = EMPTY) condition is restored for the non-empty + * degree lists. + * + * W: An integer array of size n. The flag array W determines the status of + * elements and variables, and the external degree of elements. + * + * for elements: + * if W [e] = 0, then the element e is absorbed. + * if W [e] >= wflg, then W [e] - wflg is the size of the set + * |Le \ Lme|, in terms of nonzeros (the sum of ABS (Nv [i]) for + * each principal variable i that is both in the pattern of + * element e and NOT in the pattern of the current pivot element, + * me). + * if wflg > W [e] > 0, then e is not absorbed and has not yet been + * seen in the scan of the element lists in the computation of + * |Le\Lme| in Scan 1 below. + * + * for variables: + * during supervariable detection, if W [j] != wflg then j is + * not in the pattern of variable i. + * + * The W array is initialized by setting W [i] = 1 for all i, and by + * setting wflg = 2. It is reinitialized if wflg becomes too large (to + * ensure that wflg+n does not cause integer overflow). + + * ---------------------------------------------------------------------------- + * LOCAL INTEGERS: + * ---------------------------------------------------------------------------- + */ + + Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, + jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, + nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, x, ok, ndense, ncmpa, + dense, aggressive ; + + unsigned Int hash ; /* unsigned, so that hash % n is well defined.*/ + +/* + * deg: the degree of a variable or element + * degme: size, |Lme|, of the current element, me (= Degree [me]) + * dext: external degree, |Le \ Lme|, of some element e + * lemax: largest |Le| seen so far (called dmax in Fortran version) + * e: an element + * elenme: the length, Elen [me], of element list of pivotal variable + * eln: the length, Elen [...], of an element list + * hash: the computed value of the hash function + * i: a supervariable + * ilast: the entry in a link list preceding i + * inext: the entry in a link list following i + * j: a supervariable + * jlast: the entry in a link list preceding j + * jnext: the entry in a link list, or path, following j + * k: the pivot order of an element or variable + * knt1: loop counter used during element construction + * knt2: loop counter used during element construction + * knt3: loop counter used during compression + * lenj: Len [j] + * ln: length of a supervariable list + * me: current supervariable being eliminated, and the current + * element created by eliminating that supervariable + * mindeg: current minimum degree + * nel: number of pivots selected so far + * nleft: n - nel, the number of nonpivotal rows/columns remaining + * nvi: the number of variables in a supervariable i (= Nv [i]) + * nvj: the number of variables in a supervariable j (= Nv [j]) + * nvpiv: number of pivots in current element + * slenme: number of variables in variable list of pivotal variable + * wbig: = INT_MAX - n for the "int" version, LONG_MAX - n for the + * "long" version. wflg is not allowed to be >= wbig. + * we: W [e] + * wflg: used for flagging the W array. See description of Iw. + * wnvi: wflg - Nv [i] + * x: either a supervariable or an element + * + * ok: true if supervariable j can be absorbed into i + * ndense: number of "dense" rows/columns + * dense: rows/columns with initial degree > dense are considered "dense" + * aggressive: true if aggressive absorption is being performed + * ncmpa: number of garbage collections + + * ---------------------------------------------------------------------------- + * LOCAL DOUBLES, used for statistical output only (except for alpha): + * ---------------------------------------------------------------------------- + */ + + double f, r, ndiv, s, nms_lu, nms_ldl, dmax, alpha, lnz, lnzme ; + +/* + * f: nvpiv + * r: degme + nvpiv + * ndiv: number of divisions for LU or LDL' factorizations + * s: number of multiply-subtract pairs for LU factorization, for the + * current element me + * nms_lu number of multiply-subtract pairs for LU factorization + * nms_ldl number of multiply-subtract pairs for LDL' factorization + * dmax: the largest number of entries in any column of L, including the + * diagonal + * alpha: "dense" degree ratio + * lnz: the number of nonzeros in L (excluding the diagonal) + * lnzme: the number of nonzeros in L (excl. the diagonal) for the + * current element me + + * ---------------------------------------------------------------------------- + * LOCAL "POINTERS" (indices into the Iw array) + * ---------------------------------------------------------------------------- +*/ + + Int p, p1, p2, p3, p4, pdst, pend, pj, pme, pme1, pme2, pn, psrc ; + +/* + * Any parameter (Pe [...] or pfree) or local variable starting with "p" (for + * Pointer) is an index into Iw, and all indices into Iw use variables starting + * with "p." The only exception to this rule is the iwlen input argument. + * + * p: pointer into lots of things + * p1: Pe [i] for some variable i (start of element list) + * p2: Pe [i] + Elen [i] - 1 for some variable i + * p3: index of first supervariable in clean list + * p4: + * pdst: destination pointer, for compression + * pend: end of memory to compress + * pj: pointer into an element or variable + * pme: pointer into the current element (pme1...pme2) + * pme1: the current element, me, is stored in Iw [pme1...pme2] + * pme2: the end of the current element + * pn: pointer into a "clean" variable, also used to compress + * psrc: source pointer, for compression +*/ + +/* ========================================================================= */ +/* INITIALIZATIONS */ +/* ========================================================================= */ + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is actually required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be slow. For better performance, at least + * size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + ASSERT (n > 0) ; + + /* initialize output statistics */ + lnz = 0 ; + ndiv = 0 ; + nms_lu = 0 ; + nms_ldl = 0 ; + dmax = 1 ; + me = EMPTY ; + + wflg = 2 ; + mindeg = 0 ; + ncmpa = 0 ; + nel = 0 ; + lemax = 0 ; /* this is called dmax in the Fortran version */ + +#ifdef TEST_FOR_INTEGER_OVERFLOW + /* for testing only */ + wbig = 3*n ; +#else + /* normal operation */ + wbig = Int_MAX - n ; +#endif + + /* get control parameters */ + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = (Control [AMD_AGGRESSIVE] != 0) ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + if (alpha < 0) + { + /* no dense rows/columns */ + dense = n ; + } + else + { + dense = alpha * sqrt ((double) n) ; + } + dense = MAX (16, dense) ; + dense = MIN (n, dense) ; + AMD_DEBUG1 (("AMD (debug), alpha %g, aggr. "ID"\n", alpha, aggressive)) ; + + for (i = 0 ; i < n ; i++) + { + Last [i] = EMPTY ; + Head [i] = EMPTY ; + Next [i] = EMPTY ; + /* if seperate Hhead array is used for hash buckets: * + Hhead [i] = EMPTY ; + */ + Nv [i] = 1 ; + W [i] = 1 ; + Elen [i] = 0 ; + Degree [i] = Len [i] ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; + AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, + Head, Elen, Degree, W, -1) ; +#endif + + /* --------------------------------------------------------------------- */ + /* initialize degree lists and eliminate dense and empty rows */ + /* --------------------------------------------------------------------- */ + + ndense = 0 ; + + /* for (i = n-1 ; i >= 0 ; i--) */ + for (i = 0 ; i < n ; i++) + { + deg = Degree [i] ; + ASSERT (deg >= 0 && deg < n) ; + if (deg == 0) + { + + /* ------------------------------------------------------------- + * we have a variable that can be eliminated at once because + * there is no off-diagonal non-zero in its row. Note that + * Nv [i] = 1 for an empty variable i. It is treated just + * the same as an eliminated element i. + * ------------------------------------------------------------- */ + + Elen [i] = FLIP (1) ; + nel++ ; + Pe [i] = EMPTY ; + W [i] = 0 ; + + } + else if (deg > dense) + { + + /* ------------------------------------------------------------- + * Dense variables are not treated as elements, but as unordered, + * non-principal variables that have no parent. They do not take + * part in the postorder, since Nv [i] = 0. Note that the Fortran + * version does not have this option. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Dense node "ID" degree "ID"\n", i, deg)) ; + ndense++ ; + Nv [i] = 0 ; /* do not postorder this node */ + Elen [i] = EMPTY ; + nel++ ; + Pe [i] = EMPTY ; + + } + else + { + + /* ------------------------------------------------------------- + * place i in the degree list corresponding to its degree + * ------------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Head [deg] = i ; + + } + } + +/* ========================================================================= */ +/* WHILE (selecting pivots) DO */ +/* ========================================================================= */ + + while (nel < n) + { + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; + if (AMD_debug >= 2) AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, + Last, Head, Elen, Degree, W, nel) ; +#endif + +/* ========================================================================= */ +/* GET PIVOT OF MINIMUM DEGREE */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- */ + /* find next supervariable for elimination */ + /* ----------------------------------------------------------------- */ + + ASSERT (mindeg >= 0 && mindeg < n) ; + for (deg = mindeg ; deg < n ; deg++) + { + me = Head [deg] ; + if (me != EMPTY) break ; + } + mindeg = deg ; + ASSERT (me >= 0 && me < n) ; + AMD_DEBUG1 (("=================me: "ID"\n", me)) ; + + /* ----------------------------------------------------------------- */ + /* remove chosen variable from link list */ + /* ----------------------------------------------------------------- */ + + inext = Next [me] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = EMPTY ; + Head [deg] = inext ; + + /* ----------------------------------------------------------------- */ + /* me represents the elimination of pivots nel to nel+Nv[me]-1. */ + /* place me itself as the first in this set. */ + /* ----------------------------------------------------------------- */ + + elenme = Elen [me] ; + nvpiv = Nv [me] ; + ASSERT (nvpiv > 0) ; + nel += nvpiv ; + +/* ========================================================================= */ +/* CONSTRUCT NEW ELEMENT */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * At this point, me is the pivotal supervariable. It will be + * converted into the current element. Scan list of the pivotal + * supervariable, me, setting tree pointers and constructing new list + * of supervariables for the new element, me. p is a pointer to the + * current position in the old list. + * ----------------------------------------------------------------- */ + + /* flag the variable "me" as being in Lme by negating Nv [me] */ + Nv [me] = -nvpiv ; + degme = 0 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + if (elenme == 0) + { + + /* ------------------------------------------------------------- */ + /* construct the new element in place */ + /* ------------------------------------------------------------- */ + + pme1 = Pe [me] ; + pme2 = pme1 - 1 ; + + for (p = pme1 ; p <= pme1 + Len [me] - 1 ; p++) + { + i = Iw [p] ; + ASSERT (i >= 0 && i < n && Nv [i] >= 0) ; + nvi = Nv [i] ; + if (nvi > 0) + { + + /* ----------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme. */ + /* store i in new list */ + /* ----------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [++pme2] = i ; + + /* ----------------------------------------------------- */ + /* remove variable i from degree list. */ + /* ----------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + } + else + { + + /* ------------------------------------------------------------- */ + /* construct the new element in empty space, Iw [pfree ...] */ + /* ------------------------------------------------------------- */ + + p = Pe [me] ; + pme1 = pfree ; + slenme = Len [me] - elenme ; + + for (knt1 = 1 ; knt1 <= elenme + 1 ; knt1++) + { + + if (knt1 > elenme) + { + /* search the supervariables in me. */ + e = me ; + pj = p ; + ln = slenme ; + AMD_DEBUG2 (("Search sv: "ID" "ID" "ID"\n", me,pj,ln)) ; + } + else + { + /* search the elements in me. */ + e = Iw [p++] ; + ASSERT (e >= 0 && e < n) ; + pj = Pe [e] ; + ln = Len [e] ; + AMD_DEBUG2 (("Search element e "ID" in me "ID"\n", e,me)) ; + ASSERT (Elen [e] < EMPTY && W [e] > 0 && pj >= 0) ; + } + ASSERT (ln >= 0 && (ln == 0 || (pj >= 0 && pj < iwlen))) ; + + /* --------------------------------------------------------- + * search for different supervariables and add them to the + * new list, compressing when necessary. this loop is + * executed once for each element in the list and once for + * all the supervariables in the list. + * --------------------------------------------------------- */ + + for (knt2 = 1 ; knt2 <= ln ; knt2++) + { + i = Iw [pj++] ; + ASSERT (i >= 0 && i < n && (i == me || Elen [i] >= EMPTY)); + nvi = Nv [i] ; + AMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", + i, Elen [i], Nv [i], wflg)) ; + + if (nvi > 0) + { + + /* ------------------------------------------------- */ + /* compress Iw, if necessary */ + /* ------------------------------------------------- */ + + if (pfree >= iwlen) + { + + AMD_DEBUG1 (("GARBAGE COLLECTION\n")) ; + + /* prepare for compressing Iw by adjusting pointers + * and lengths so that the lists being searched in + * the inner and outer loops contain only the + * remaining entries. */ + + Pe [me] = p ; + Len [me] -= knt1 ; + /* check if nothing left of supervariable me */ + if (Len [me] == 0) Pe [me] = EMPTY ; + Pe [e] = pj ; + Len [e] = ln - knt2 ; + /* nothing left of element e */ + if (Len [e] == 0) Pe [e] = EMPTY ; + + ncmpa++ ; /* one more garbage collection */ + + /* store first entry of each object in Pe */ + /* FLIP the first entry in each object */ + for (j = 0 ; j < n ; j++) + { + pn = Pe [j] ; + if (pn >= 0) + { + ASSERT (pn >= 0 && pn < iwlen) ; + Pe [j] = Iw [pn] ; + Iw [pn] = FLIP (j) ; + } + } + + /* psrc/pdst point to source/destination */ + psrc = 0 ; + pdst = 0 ; + pend = pme1 - 1 ; + + while (psrc <= pend) + { + /* search for next FLIP'd entry */ + j = FLIP (Iw [psrc++]) ; + if (j >= 0) + { + AMD_DEBUG2 (("Got object j: "ID"\n", j)) ; + Iw [pdst] = Pe [j] ; + Pe [j] = pdst++ ; + lenj = Len [j] ; + /* copy from source to destination */ + for (knt3 = 0 ; knt3 <= lenj - 2 ; knt3++) + { + Iw [pdst++] = Iw [psrc++] ; + } + } + } + + /* move the new partially-constructed element */ + p1 = pdst ; + for (psrc = pme1 ; psrc <= pfree-1 ; psrc++) + { + Iw [pdst++] = Iw [psrc] ; + } + pme1 = p1 ; + pfree = pdst ; + pj = Pe [e] ; + p = Pe [me] ; + + } + + /* ------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme */ + /* store i in new list */ + /* ------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [pfree++] = i ; + AMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); + + /* ------------------------------------------------- */ + /* remove variable i from degree link list */ + /* ------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + + if (e != me) + { + /* set tree pointer and flag to indicate element e is + * absorbed into new element me (the parent of e is me) */ + AMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + + pme2 = pfree - 1 ; + } + + /* ----------------------------------------------------------------- */ + /* me has now been converted into an element in Iw [pme1..pme2] */ + /* ----------------------------------------------------------------- */ + + /* degme holds the external degree of new element */ + Degree [me] = degme ; + Pe [me] = pme1 ; + Len [me] = pme2 - pme1 + 1 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + Elen [me] = FLIP (nvpiv + degme) ; + /* FLIP (Elen (me)) is now the degree of pivot (including + * diagonal part). */ + +#ifndef NDEBUG + AMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; + for (pme = pme1 ; pme <= pme2 ; pme++) AMD_DEBUG3 ((" "ID"", Iw[pme])); + AMD_DEBUG3 (("\n")) ; +#endif + + /* ----------------------------------------------------------------- */ + /* make sure that wflg is not too large. */ + /* ----------------------------------------------------------------- */ + + /* With the current value of wflg, wflg+n must not cause integer + * overflow */ + + if (wflg >= wbig) + { + for (x = 0 ; x < n ; x++) + { + if (W [x] != 0) W [x] = 1 ; + } + wflg = 2 ; + } + +/* ========================================================================= */ +/* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 1: compute the external degrees of previous elements with + * respect to the current element. That is: + * (W [e] - wflg) = |Le \ Lme| + * for each element e that appears in any supervariable in Lme. The + * notation Le refers to the pattern (list of supervariables) of a + * previous element e, where e is not yet absorbed, stored in + * Iw [Pe [e] + 1 ... Pe [e] + Iw [Pe [e]]]. The notation Lme + * refers to the pattern of the current element (stored in + * Iw [pme1..pme2]). If aggressive absorption is enabled, and + * (W [e] - wflg) becomes zero, then the element e will be absorbed + * in Scan 2. + * ----------------------------------------------------------------- */ + + AMD_DEBUG2 (("me: ")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + eln = Elen [i] ; + AMD_DEBUG3 ((""ID" Elen "ID": \n", i, eln)) ; + if (eln > 0) + { + /* note that Nv [i] has been negated to denote i in Lme: */ + nvi = -Nv [i] ; + ASSERT (nvi > 0 && Pe [i] >= 0 && Pe [i] < iwlen) ; + wnvi = wflg - nvi ; + for (p = Pe [i] ; p <= Pe [i] + eln - 1 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + AMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; + if (we >= wflg) + { + /* unabsorbed element e has been seen in this loop */ + AMD_DEBUG4 ((" unabsorbed, first time seen")) ; + we -= nvi ; + } + else if (we != 0) + { + /* e is an unabsorbed element */ + /* this is the first we have seen e in all of Scan 1 */ + AMD_DEBUG4 ((" unabsorbed")) ; + we = Degree [e] + wnvi ; + } + AMD_DEBUG4 (("\n")) ; + W [e] = we ; + } + } + } + AMD_DEBUG2 (("\n")) ; + +/* ========================================================================= */ +/* DEGREE UPDATE AND ELEMENT ABSORPTION */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 2: for each i in Lme, sum up the degree of Lme (which is + * degme), plus the sum of the external degrees of each Le for the + * elements e appearing within i, plus the supervariables in i. + * Place i in hash list. + * ----------------------------------------------------------------- */ + + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n && Nv [i] < 0 && Elen [i] >= 0) ; + AMD_DEBUG2 (("Updating: i "ID" "ID" "ID"\n", i, Elen[i], Len [i])); + p1 = Pe [i] ; + p2 = p1 + Elen [i] - 1 ; + pn = p1 ; + hash = 0 ; + deg = 0 ; + ASSERT (p1 >= 0 && p1 < iwlen && p2 >= -1 && p2 < iwlen) ; + + /* ------------------------------------------------------------- */ + /* scan the element list associated with supervariable i */ + /* ------------------------------------------------------------- */ + + /* UMFPACK/MA38-style approximate degree: */ + if (aggressive) + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + /* dext = | Le \ Lme | */ + dext = we - wflg ; + if (dext > 0) + { + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + else + { + /* external degree of e is zero, absorb e into me*/ + AMD_DEBUG1 ((" Element "ID" =>"ID" (aggressive)\n", + e, me)) ; + ASSERT (dext == 0) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + } + } + else + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + dext = we - wflg ; + ASSERT (dext >= 0) ; + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + } + } + + /* count the number of elements in i (including me): */ + Elen [i] = pn - p1 + 1 ; + + /* ------------------------------------------------------------- */ + /* scan the supervariables in the list associated with i */ + /* ------------------------------------------------------------- */ + + /* The bulk of the AMD run time is typically spent in this loop, + * particularly if the matrix has many dense rows that are not + * removed prior to ordering. */ + p3 = pn ; + p4 = p1 + Len [i] ; + for (p = p2 + 1 ; p < p4 ; p++) + { + j = Iw [p] ; + ASSERT (j >= 0 && j < n) ; + nvj = Nv [j] ; + if (nvj > 0) + { + /* j is unabsorbed, and not in Lme. */ + /* add to degree and add to new list */ + deg += nvj ; + Iw [pn++] = j ; + hash += j ; + AMD_DEBUG4 ((" s: "ID" hash "ID" Nv[j]= "ID"\n", + j, hash, nvj)) ; + } + } + + /* ------------------------------------------------------------- */ + /* update the degree and check for mass elimination */ + /* ------------------------------------------------------------- */ + + /* with aggressive absorption, deg==0 is identical to the + * Elen [i] == 1 && p3 == pn test, below. */ + ASSERT (IMPLIES (aggressive, (deg==0) == (Elen[i]==1 && p3==pn))) ; + + if (Elen [i] == 1 && p3 == pn) + { + + /* --------------------------------------------------------- */ + /* mass elimination */ + /* --------------------------------------------------------- */ + + /* There is nothing left of this node except for an edge to + * the current pivot element. Elen [i] is 1, and there are + * no variables adjacent to node i. Absorb i into the + * current pivot element, me. Note that if there are two or + * more mass eliminations, fillin due to mass elimination is + * possible within the nvpiv-by-nvpiv pivot block. It is this + * step that causes AMD's analysis to be an upper bound. + * + * The reason is that the selected pivot has a lower + * approximate degree than the true degree of the two mass + * eliminated nodes. There is no edge between the two mass + * eliminated nodes. They are merged with the current pivot + * anyway. + * + * No fillin occurs in the Schur complement, in any case, + * and this effect does not decrease the quality of the + * ordering itself, just the quality of the nonzero and + * flop count analysis. It also means that the post-ordering + * is not an exact elimination tree post-ordering. */ + + AMD_DEBUG1 ((" MASS i "ID" => parent e "ID"\n", i, me)) ; + Pe [i] = FLIP (me) ; + nvi = -Nv [i] ; + degme -= nvi ; + nvpiv += nvi ; + nel += nvi ; + Nv [i] = 0 ; + Elen [i] = EMPTY ; + + } + else + { + + /* --------------------------------------------------------- */ + /* update the upper-bound degree of i */ + /* --------------------------------------------------------- */ + + /* the following degree does not yet include the size + * of the current element, which is added later: */ + + Degree [i] = MIN (Degree [i], deg) ; + + /* --------------------------------------------------------- */ + /* add me to the list for i */ + /* --------------------------------------------------------- */ + + /* move first supervariable to end of list */ + Iw [pn] = Iw [p3] ; + /* move first element to end of element part of list */ + Iw [p3] = Iw [p1] ; + /* add new element, me, to front of list. */ + Iw [p1] = me ; + /* store the new length of the list in Len [i] */ + Len [i] = pn - p1 + 1 ; + + /* --------------------------------------------------------- */ + /* place in hash bucket. Save hash key of i in Last [i]. */ + /* --------------------------------------------------------- */ + + /* NOTE: this can fail if hash is negative, because the ANSI C + * standard does not define a % b when a and/or b are negative. + * That's why hash is defined as an unsigned Int, to avoid this + * problem. */ + hash = hash % n ; + ASSERT (((Int) hash) >= 0 && ((Int) hash) < n) ; + + /* if the Hhead array is not used: */ + j = Head [hash] ; + if (j <= EMPTY) + { + /* degree list is empty, hash head is FLIP (j) */ + Next [i] = FLIP (j) ; + Head [hash] = FLIP (i) ; + } + else + { + /* degree list is not empty, use Last [Head [hash]] as + * hash head. */ + Next [i] = Last [j] ; + Last [j] = i ; + } + + /* if a seperate Hhead array is used: * + Next [i] = Hhead [hash] ; + Hhead [hash] = i ; + */ + + Last [i] = hash ; + } + } + + Degree [me] = degme ; + + /* ----------------------------------------------------------------- */ + /* Clear the counter array, W [...], by incrementing wflg. */ + /* ----------------------------------------------------------------- */ + + /* make sure that wflg+n does not cause integer overflow */ + lemax = MAX (lemax, degme) ; + wflg += lemax ; + if (wflg >= wbig) + { + for (x = 0 ; x < n ; x++) + { + if (W [x] != 0) W [x] = 1 ; + } + wflg = 2 ; + } + /* at this point, W [0..n-1] < wflg holds */ + +/* ========================================================================= */ +/* SUPERVARIABLE DETECTION */ +/* ========================================================================= */ + + AMD_DEBUG1 (("Detecting supervariables:\n")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + AMD_DEBUG2 (("Consider i "ID" nv "ID"\n", i, Nv [i])) ; + if (Nv [i] < 0) + { + /* i is a principal variable in Lme */ + + /* --------------------------------------------------------- + * examine all hash buckets with 2 or more variables. We do + * this by examing all unique hash keys for supervariables in + * the pattern Lme of the current element, me + * --------------------------------------------------------- */ + + /* let i = head of hash bucket, and empty the hash bucket */ + ASSERT (Last [i] >= 0 && Last [i] < n) ; + hash = Last [i] ; + + /* if Hhead array is not used: */ + j = Head [hash] ; + if (j == EMPTY) + { + /* hash bucket and degree list are both empty */ + i = EMPTY ; + } + else if (j < EMPTY) + { + /* degree list is empty */ + i = FLIP (j) ; + Head [hash] = EMPTY ; + } + else + { + /* degree list is not empty, restore Last [j] of head j */ + i = Last [j] ; + Last [j] = EMPTY ; + } + + /* if seperate Hhead array is used: * + i = Hhead [hash] ; + Hhead [hash] = EMPTY ; + */ + + ASSERT (i >= EMPTY && i < n) ; + AMD_DEBUG2 (("----i "ID" hash "ID"\n", i, hash)) ; + + while (i != EMPTY && Next [i] != EMPTY) + { + + /* ----------------------------------------------------- + * this bucket has one or more variables following i. + * scan all of them to see if i can absorb any entries + * that follow i in hash bucket. Scatter i into w. + * ----------------------------------------------------- */ + + ln = Len [i] ; + eln = Elen [i] ; + ASSERT (ln >= 0 && eln >= 0) ; + ASSERT (Pe [i] >= 0 && Pe [i] < iwlen) ; + /* do not flag the first element in the list (me) */ + for (p = Pe [i] + 1 ; p <= Pe [i] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + W [Iw [p]] = wflg ; + } + + /* ----------------------------------------------------- */ + /* scan every other entry j following i in bucket */ + /* ----------------------------------------------------- */ + + jlast = i ; + j = Next [i] ; + ASSERT (j >= EMPTY && j < n) ; + + while (j != EMPTY) + { + /* ------------------------------------------------- */ + /* check if j and i have identical nonzero pattern */ + /* ------------------------------------------------- */ + + AMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; + + /* check if i and j have the same Len and Elen */ + ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; + ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; + ok = (Len [j] == ln) && (Elen [j] == eln) ; + /* skop the first element in the list (me) */ + for (p = Pe [j] + 1 ; ok && p <= Pe [j] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + if (W [Iw [p]] != wflg) ok = 0 ; + } + if (ok) + { + /* --------------------------------------------- */ + /* found it! j can be absorbed into i */ + /* --------------------------------------------- */ + + AMD_DEBUG1 (("found it! j "ID" => i "ID"\n", j,i)); + Pe [j] = FLIP (i) ; + /* both Nv [i] and Nv [j] are negated since they */ + /* are in Lme, and the absolute values of each */ + /* are the number of variables in i and j: */ + Nv [i] += Nv [j] ; + Nv [j] = 0 ; + Elen [j] = EMPTY ; + /* delete j from hash bucket */ + ASSERT (j != Next [j]) ; + j = Next [j] ; + Next [jlast] = j ; + + } + else + { + /* j cannot be absorbed into i */ + jlast = j ; + ASSERT (j != Next [j]) ; + j = Next [j] ; + } + ASSERT (j >= EMPTY && j < n) ; + } + + /* ----------------------------------------------------- + * no more variables can be absorbed into i + * go to next i in bucket and clear flag array + * ----------------------------------------------------- */ + + wflg++ ; + i = Next [i] ; + ASSERT (i >= EMPTY && i < n) ; + + } + } + } + AMD_DEBUG2 (("detect done\n")) ; + +/* ========================================================================= */ +/* RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVARIABLES FROM ELEMENT */ +/* ========================================================================= */ + + p = pme1 ; + nleft = n - nel ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + nvi = -Nv [i] ; + AMD_DEBUG3 (("Restore i "ID" "ID"\n", i, nvi)) ; + if (nvi > 0) + { + /* i is a principal variable in Lme */ + /* restore Nv [i] to signify that i is principal */ + Nv [i] = nvi ; + + /* --------------------------------------------------------- */ + /* compute the external degree (add size of current element) */ + /* --------------------------------------------------------- */ + + deg = Degree [i] + degme - nvi ; + deg = MIN (deg, nleft - nvi) ; + ASSERT (IMPLIES (aggressive, deg > 0) && deg >= 0 && deg < n) ; + + /* --------------------------------------------------------- */ + /* place the supervariable at the head of the degree list */ + /* --------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Last [i] = EMPTY ; + Head [deg] = i ; + + /* --------------------------------------------------------- */ + /* save the new degree, and find the minimum degree */ + /* --------------------------------------------------------- */ + + mindeg = MIN (mindeg, deg) ; + Degree [i] = deg ; + + /* --------------------------------------------------------- */ + /* place the supervariable in the element pattern */ + /* --------------------------------------------------------- */ + + Iw [p++] = i ; + + } + } + AMD_DEBUG2 (("restore done\n")) ; + +/* ========================================================================= */ +/* FINALIZE THE NEW ELEMENT */ +/* ========================================================================= */ + + AMD_DEBUG2 (("ME = "ID" DONE\n", me)) ; + Nv [me] = nvpiv ; + /* save the length of the list for the new element me */ + Len [me] = p - pme1 ; + if (Len [me] == 0) + { + /* there is nothing left of the current pivot element */ + /* it is a root of the assembly tree */ + Pe [me] = EMPTY ; + W [me] = 0 ; + } + if (elenme != 0) + { + /* element was not constructed in place: deallocate part of */ + /* it since newly nonprincipal variables may have been removed */ + pfree = p ; + } + + /* The new element has nvpiv pivots and the size of the contribution + * block for a multifrontal method is degme-by-degme, not including + * the "dense" rows/columns. If the "dense" rows/columns are included, + * the frontal matrix is no larger than + * (degme+ndense)-by-(degme+ndense). + */ + + if (Info != (double *) NULL) + { + f = nvpiv ; + r = degme + ndense ; + dmax = MAX (dmax, f + r) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = f*r + (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = f*r*r + r*(f-1)*f + (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + } + +#ifndef NDEBUG + AMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; + for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) + { + AMD_DEBUG3 ((" "ID"", Iw [pme])) ; + } + AMD_DEBUG3 (("\n")) ; +#endif + + } + +/* ========================================================================= */ +/* DONE SELECTING PIVOTS */ +/* ========================================================================= */ + + if (Info != (double *) NULL) + { + + /* count the work to factorize the ndense-by-ndense submatrix */ + f = ndense ; + dmax = MAX (dmax, (double) ndense) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + + /* number of nz's in L (excl. diagonal) */ + Info [AMD_LNZ] = lnz ; + + /* number of divide ops for LU and LDL' */ + Info [AMD_NDIV] = ndiv ; + + /* number of multiply-subtract pairs for LDL' */ + Info [AMD_NMULTSUBS_LDL] = nms_ldl ; + + /* number of multiply-subtract pairs for LU */ + Info [AMD_NMULTSUBS_LU] = nms_lu ; + + /* number of "dense" rows/columns */ + Info [AMD_NDENSE] = ndense ; + + /* largest front is dmax-by-dmax */ + Info [AMD_DMAX] = dmax ; + + /* number of garbage collections in AMD */ + Info [AMD_NCMPA] = ncmpa ; + + /* successful ordering */ + Info [AMD_STATUS] = AMD_OK ; + } + +/* ------------------------------------------------------------------------- + * Variables at this point: + * + * Pe: holds the elimination tree. The parent of j is FLIP (Pe [j]), + * or EMPTY if j is a root. The tree holds both elements and + * non-principal (unordered) variables absorbed into them. + * Dense variables are non-principal and unordered. + * + * Elen: holds the size of each element, including the diagonal part. + * FLIP (Elen [e]) > 0 if e is an element. For unordered + * variables i, Elen [i] is EMPTY. + * + * Nv: Nv [e] > 0 is the number of pivots represented by the element e. + * For unordered variables i, Nv [i] is zero. + * + * Contents no longer needed: + * W, Iw, Len, Degree, Head, Next, Last. + * + * The matrix itself has been destroyed. + * + * n: the size of the matrix. + * No other scalars needed (pfree, iwlen, etc.) + * ------------------------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + Pe [i] = FLIP (Pe [i]) ; + Elen [i] = FLIP (Elen [i]) ; + } + +/* Now the parent of j is Pe [j], or EMPTY if j is a root. Elen [e] > 0 + * is the size of element e. Elen [i] is EMPTY for unordered variable i. */ + +#ifndef NDEBUG + AMD_DEBUG2 (("\nTree:\n")) ; + for (i = 0 ; i < n ; i++) + { + AMD_DEBUG2 ((" "ID" parent: "ID" ", i, Pe [i])) ; + ASSERT (Pe [i] >= EMPTY && Pe [i] < n) ; + if (Nv [i] > 0) + { + /* this is an element */ + e = i ; + AMD_DEBUG2 ((" element, size is "ID"\n", Elen [i])) ; + ASSERT (Elen [e] > 0) ; + } + AMD_DEBUG2 (("\n")) ; + } + AMD_DEBUG2 (("\nelements:\n")) ; + for (e = 0 ; e < n ; e++) + { + if (Nv [e] > 0) + { + AMD_DEBUG3 (("Element e= "ID" size "ID" nv "ID" \n", e, + Elen [e], Nv [e])) ; + } + } + AMD_DEBUG2 (("\nvariables:\n")) ; + for (i = 0 ; i < n ; i++) + { + Int cnt ; + if (Nv [i] == 0) + { + AMD_DEBUG3 (("i unordered: "ID"\n", i)) ; + j = Pe [i] ; + cnt = 0 ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + AMD_DEBUG3 ((" i is a dense variable\n")) ; + } + else + { + ASSERT (j >= 0 && j < n) ; + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + cnt++ ; + if (cnt > n) break ; + } + e = j ; + AMD_DEBUG3 ((" got to e: "ID"\n", e)) ; + } + } + } +#endif + +/* ========================================================================= */ +/* compress the paths of the variables */ +/* ========================================================================= */ + + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + + /* ------------------------------------------------------------- + * i is an un-ordered row. Traverse the tree from i until + * reaching an element, e. The element, e, was the principal + * supervariable of i and all nodes in the path from i to when e + * was selected as pivot. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Path compression, i unordered: "ID"\n", i)) ; + j = Pe [i] ; + ASSERT (j >= EMPTY && j < n) ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + /* Skip a dense variable. It has no parent. */ + AMD_DEBUG3 ((" i is a dense variable\n")) ; + continue ; + } + + /* while (j is a variable) */ + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + ASSERT (j >= 0 && j < n) ; + } + /* got to an element e */ + e = j ; + AMD_DEBUG3 (("got to e: "ID"\n", e)) ; + + /* ------------------------------------------------------------- + * traverse the path again from i to e, and compress the path + * (all nodes point to e). Path compression allows this code to + * compute in O(n) time. + * ------------------------------------------------------------- */ + + j = i ; + /* while (j is a variable) */ + while (Nv [j] == 0) + { + jnext = Pe [j] ; + AMD_DEBUG3 (("j "ID" jnext "ID"\n", j, jnext)) ; + Pe [j] = e ; + j = jnext ; + ASSERT (j >= 0 && j < n) ; + } + } + } + +/* ========================================================================= */ +/* postorder the assembly tree */ +/* ========================================================================= */ + + AMD_postorder (n, Pe, Nv, Elen, + W, /* output order */ + Head, Next, Last) ; /* workspace */ + +/* ========================================================================= */ +/* compute output permutation and inverse permutation */ +/* ========================================================================= */ + + /* W [e] = k means that element e is the kth element in the new + * order. e is in the range 0 to n-1, and k is in the range 0 to + * the number of elements. Use Head for inverse order. */ + + for (k = 0 ; k < n ; k++) + { + Head [k] = EMPTY ; + Next [k] = EMPTY ; + } + for (e = 0 ; e < n ; e++) + { + k = W [e] ; + ASSERT ((k == EMPTY) == (Nv [e] == 0)) ; + if (k != EMPTY) + { + ASSERT (k >= 0 && k < n) ; + Head [k] = e ; + } + } + + /* construct output inverse permutation in Next, + * and permutation in Last */ + nel = 0 ; + for (k = 0 ; k < n ; k++) + { + e = Head [k] ; + if (e == EMPTY) break ; + ASSERT (e >= 0 && e < n && Nv [e] > 0) ; + Next [e] = nel ; + nel += Nv [e] ; + } + ASSERT (nel == n - ndense) ; + + /* order non-principal variables (dense, & those merged into supervar's) */ + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + e = Pe [i] ; + ASSERT (e >= EMPTY && e < n) ; + if (e != EMPTY) + { + /* This is an unordered variable that was merged + * into element e via supernode detection or mass + * elimination of i when e became the pivot element. + * Place i in order just before e. */ + ASSERT (Next [i] == EMPTY && Nv [e] > 0) ; + Next [i] = Next [e] ; + Next [e]++ ; + } + else + { + /* This is a dense unordered variable, with no parent. + * Place it last in the output order. */ + Next [i] = nel++ ; + } + } + } + ASSERT (nel == n) ; + + AMD_DEBUG2 (("\n\nPerm:\n")) ; + for (i = 0 ; i < n ; i++) + { + k = Next [i] ; + ASSERT (k >= 0 && k < n) ; + Last [k] = i ; + AMD_DEBUG2 ((" perm ["ID"] = "ID"\n", k, i)) ; + } +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_aat.c b/liboctave/UMFPACK/AMD/Source/amd_aat.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_aat.c @@ -0,0 +1,180 @@ +/* ========================================================================= */ +/* === AMD_aat ============================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_aat: compute the symmetry of the pattern of A, and count the number of + * nonzeros each column of A+A' (excluding the diagonal). Assume the input + * matrix has no errors. + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_aat /* returns nz in A+A' */ +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/ + Int Tp [ ], /* workspace of size n */ + double Info [ ] +) +{ + Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz, nzaat ; + double sym ; + +#ifndef NDEBUG + AMD_debug_init ("AMD AAT") ; + for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; + ASSERT (AMD_valid (n, n, Ap, Ai)) ; +#endif + + if (Info != (double *) NULL) + { + /* clear the Info array, if it exists */ + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_STATUS] = AMD_OK ; + } + + for (k = 0 ; k < n ; k++) + { + Len [k] = 0 ; + } + + nzdiag = 0 ; + nzboth = 0 ; + nz = Ap [n] ; + + for (k = 0 ; k < n ; k++) + { + p1 = Ap [k] ; + p2 = Ap [k+1] ; + AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + if (j < k) + { + /* entry A (j,k) is in the strictly upper triangular part, + * add both A (j,k) and A (k,j) to the matrix A+A' */ + Len [j]++ ; + Len [k]++ ; + AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j)); + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + nzdiag++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Tp [j] != EMPTY) ; + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + nzboth++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + /* Tp [k] points to the entry just below the diagonal in column k */ + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + } + } + + /* --------------------------------------------------------------------- */ + /* compute the symmetry of the nonzero pattern of A */ + /* --------------------------------------------------------------------- */ + + /* Given a matrix A, the symmetry of A is: + * B = tril (spones (A), -1) + triu (spones (A), 1) ; + * sym = nnz (B & B') / nnz (B) ; + * or 1 if nnz (B) is zero. + */ + + if (nz == nzdiag) + { + sym = 1 ; + } + else + { + sym = ((double) (2 * nzboth)) / ((double) (nz - nzdiag)) ; + } + + nzaat = 0 ; + for (k = 0 ; k < n ; k++) + { + nzaat += Len [k] ; + } + AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = "ID"\n",nzaat)); + AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", + nzboth, nz, nzdiag, sym)) ; + + if (Info != (double *) NULL) + { + Info [AMD_STATUS] = AMD_OK ; + Info [AMD_N] = n ; + Info [AMD_NZ] = nz ; + Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ + Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ + Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ + } + + return (nzaat) ; +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_control.c b/liboctave/UMFPACK/AMD/Source/amd_control.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_control.c @@ -0,0 +1,61 @@ +/* ========================================================================= */ +/* === AMD_control ========================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the control parameters for AMD. See amd.h + * for details. If the Control array is not present, the defaults are + * printed instead. + */ + +#include "amd_internal.h" + +GLOBAL void AMD_control +( + double Control [ ] +) +{ + double alpha ; + Int aggressive ; + + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = Control [AMD_AGGRESSIVE] != 0 ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + + PRINTF (("\namd: approximate minimum degree ordering, parameters:\n" + " dense row parameter: %g\n", alpha)) ; + + if (alpha < 0) + { + PRINTF ((" no rows treated as dense\n")) ; + } + else + { + PRINTF (( + " (rows with more than max (%g * sqrt (n), 16) entries are\n" + " considered \"dense\", and placed last in output permutation)\n", + alpha)) ; + } + + if (aggressive) + { + PRINTF ((" aggressive absorption: yes\n\n")) ; + } + else + { + PRINTF ((" aggressive absorption: no\n\n")) ; + } +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_defaults.c b/liboctave/UMFPACK/AMD/Source/amd_defaults.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_defaults.c @@ -0,0 +1,33 @@ +/* ========================================================================= */ +/* === AMD_defaults ======================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Sets default control parameters for AMD. See amd.h + * for details. + */ + +#include "amd_internal.h" + +GLOBAL void AMD_defaults +( + double Control [ ] +) +{ + Int i ; + if (Control != (double *) NULL) + { + for (i = 0 ; i < AMD_CONTROL ; i++) + { + Control [i] = 0 ; + } + Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; + Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; + } +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_dump.c b/liboctave/UMFPACK/AMD/Source/amd_dump.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_dump.c @@ -0,0 +1,176 @@ +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Debugging routines for AMD. Not used if NDEBUG is not defined at compile- + * time (the default). See comments in amd_internal.h on how to enable + * debugging. Not user-callable. + */ + +#include "amd_internal.h" + +#ifndef NDEBUG + +/* This global variable is present only when debugging */ +GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */ + +/* ========================================================================= */ +/* === AMD_debug_init ====================================================== */ +/* ========================================================================= */ + +/* Sets the debug print level, by reading the file debug.amd (if it exists) */ + +GLOBAL void AMD_debug_init ( char *s ) +{ + FILE *f ; + f = fopen ("debug.amd", "r") ; + if (f == (FILE *) NULL) + { + AMD_debug = -999 ; + } + else + { + fscanf (f, ID, &AMD_debug) ; + fclose (f) ; + } + if (AMD_debug >= 0) printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug); +} + +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* Dump AMD's data structure, except for the hash buckets. This routine + * cannot be called when the hash buckets are non-empty. + */ + +GLOBAL void AMD_dump ( + Int n, /* A is n-by-n */ + Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */ + Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* len [0..n-1]: length for row i */ + Int iwlen, /* length of iw */ + Int pfree, /* iw [pfree ... iwlen-1] is empty on input */ + Int Nv [ ], /* nv [0..n-1] */ + Int Next [ ], /* next [0..n-1] */ + Int Last [ ], /* last [0..n-1] */ + Int Head [ ], /* head [0..n-1] */ + Int Elen [ ], /* size n */ + Int Degree [ ], /* size n */ + Int W [ ], /* size n */ + Int nel +) +{ + Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; + + if (AMD_debug < 0) return ; + ASSERT (pfree <= iwlen) ; + for (i = 0 ; i < n ; i++) + { + pe = Pe [i] ; + elen = Elen [i] ; + nv = Nv [i] ; + len = Len [i] ; + w = W [i] ; + + if (elen >= EMPTY) + { + if (nv == 0) + { + AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ; + ASSERT (elen == EMPTY) ; + if (pe == EMPTY) + { + AMD_DEBUG3 ((" dense node\n")) ; + ASSERT (w == 1) ; + } + else + { + ASSERT (pe < EMPTY) ; + AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); + } + } + else + { + AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i)); + AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; + ASSERT (elen >= 0) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" e/s: ")) ; + if (elen == 0) AMD_DEBUG3 ((" : ")) ; + ASSERT (pe < pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + if (k == elen-1) AMD_DEBUG3 ((" : ")) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + else + { + e = i ; + if (w == 0) + { + AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe < 0) ; + AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; + } + else + { + AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" : ")) ; + ASSERT (pe < pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + } + + /* this routine cannot be called when the hash buckets are non-empty */ + AMD_DEBUG3 (("\nDegree lists:\n")) ; + if (nel >= 0) + { + cnt = 0 ; + for (deg = 0 ; deg < n ; deg++) + { + if (Head [deg] == EMPTY) continue ; + ilast = EMPTY ; + AMD_DEBUG3 ((ID": ", deg)) ; + for (i = Head [deg] ; i != EMPTY ; i = Next [i]) + { + AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n", + i, Next [i], Last [i], Degree [i])) ; + ASSERT (i >= 0 && i < n && ilast == Last [i] && + deg == Degree [i]) ; + cnt += Nv [i] ; + ilast = i ; + } + AMD_DEBUG3 (("\n")) ; + } + ASSERT (cnt == n - nel) ; + } + +} + +#endif diff --git a/liboctave/UMFPACK/AMD/Source/amd_info.c b/liboctave/UMFPACK/AMD/Source/amd_info.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_info.c @@ -0,0 +1,115 @@ +/* ========================================================================= */ +/* === AMD_info ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the output statistics for AMD. See amd.h + * for details. If the Info array is not present, nothing is printed. + */ + +#include "amd_internal.h" + +#define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }} + +GLOBAL void AMD_info +( + double Info [ ] +) +{ + double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; + + if (!Info) + { + return ; + } + + n = Info [AMD_N] ; + ndiv = Info [AMD_NDIV] ; + nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ; + nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ; + lnz = Info [AMD_LNZ] ; + lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; + + /* AMD return status */ + PRINTF (( + "\namd: approximate minimum degree ordering, results:\n" + " status: ")) ; + if (Info [AMD_STATUS] == AMD_OK) + { + PRINTF (("OK\n")) ; + } + else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) + { + PRINTF (("out of memory\n")) ; + } + else if (Info [AMD_STATUS] == AMD_INVALID) + { + PRINTF (("invalid matrix\n")) ; + } + else + { + PRINTF (("unknown\n")) ; + } + + /* statistics about the input matrix */ + PRI (" n, dimension of A: %.20g\n", n); + PRI (" nz, number of nonzeros in A: %.20g\n", + Info [AMD_NZ]) ; + PRI (" symmetry of A: %.4f\n", + Info [AMD_SYMMETRY]) ; + PRI (" number of nonzeros on diagonal: %.20g\n", + Info [AMD_NZDIAG]) ; + PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", + Info [AMD_NZ_A_PLUS_AT]) ; + PRI (" # dense rows/columns of A+A': %.20g\n", + Info [AMD_NDENSE]) ; + + /* statistics about AMD's behavior */ + PRI (" memory used, in bytes: %.20g\n", + Info [AMD_MEMORY]) ; + PRI (" # of memory compactions: %.20g\n", + Info [AMD_NCMPA]) ; + + /* statistics about the ordering quality */ + PRINTF (("\n" + " The following approximate statistics are for a subsequent\n" + " factorization of A(P,P) + A(P,P)'. They are slight upper\n" + " bounds if there are no dense rows/columns in A+A', and become\n" + " looser if dense rows/columns exist.\n\n")) ; + + PRI (" nonzeros in L (excluding diagonal): %.20g\n", + lnz) ; + PRI (" nonzeros in L (including diagonal): %.20g\n", + lnzd) ; + PRI (" # divide operations for LDL' or LU: %.20g\n", + ndiv) ; + PRI (" # multiply-subtract operations for LDL': %.20g\n", + nmultsubs_ldl) ; + PRI (" # multiply-subtract operations for LU: %.20g\n", + nmultsubs_lu) ; + PRI (" max nz. in any column of L (incl. diagonal): %.20g\n", + Info [AMD_DMAX]) ; + + /* total flop counts for various factorizations */ + + if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) + { + PRINTF (("\n" + " chol flop count for real A, sqrt counted as 1 flop: %.20g\n" + " LDL' flop count for real A: %.20g\n" + " LDL' flop count for complex A: %.20g\n" + " LU flop count for real A (with no pivoting): %.20g\n" + " LU flop count for complex A (with no pivoting): %.20g\n\n", + n + ndiv + 2*nmultsubs_ldl, + ndiv + 2*nmultsubs_ldl, + 9*ndiv + 8*nmultsubs_ldl, + ndiv + 2*nmultsubs_lu, + 9*ndiv + 8*nmultsubs_lu)) ; + } +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_internal.h b/liboctave/UMFPACK/AMD/Source/amd_internal.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_internal.h @@ -0,0 +1,426 @@ +/* ========================================================================= */ +/* === amd_internal.h ====================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* This file is for internal use in AMD itself, and does not normally need to + * be included in user code. Use amd.h instead. + * + * The following compile-time definitions affect how AMD is compiled. + * + * -DMATLAB_MEX_FILE + * + * This flag is turned on when compiling the amd mexFunction for + * use in MATLAB. + * + * -DMATHWORKS + * + * This flag is turned on when compiling amd as a built-in routine + * in MATLAB. Internal routines utMalloc, utFree, utRealloc, and + * utPrintf are used, and the MathWorks "util.h" file is included. + * This option is intended for use by The MathWorks, Inc., only. + * + * -DNDEBUG + * + * Debugging mode (if NDEBUG is not defined). The default, of course, + * is no debugging. Turning on debugging takes some work (see below). + * If you do not edit this file, then debugging is turned off anyway, + * regardless of whether or not -DNDEBUG is specified in your compiler + * options. + * + * -DALLOCATE=allocation_routine + * -DFREE=free_routine + * + * If you do not wish to use malloc or free, you can define the + * routines to be used here. You must specify both of them, or + * neither. + * + * -DPRINTF=printf_routine + * + * If you wish to use a routine other than printf, you can define it + * with -DPRINTF= followed by the name of the printf replacement. + */ + +/* ========================================================================= */ +/* === NDEBUG ============================================================== */ +/* ========================================================================= */ + +/* + AMD will be exceedingly slow when running in debug mode. The next three + lines ensure that debugging is turned off. +*/ +#ifndef NDEBUG +#define NDEBUG +#endif + +/* + To enable debugging, uncomment the following line: +#undef NDEBUG +*/ + +/* ------------------------------------------------------------------------- */ +/* ANSI include files */ +/* ------------------------------------------------------------------------- */ + +/* from stdlib.h: malloc, free, realloc (when not compiling for MATLAB) */ +#include + +/* from stdio.h: printf. When in debug mode: fopen, fscanf */ +#include + +/* from limits.h: INT_MAX and LONG_MAX */ +#include + +/* from math.h: sqrt */ +#include + +/* ------------------------------------------------------------------------- */ +/* MATLAB include files (only if being used in or via MATLAB) */ +/* ------------------------------------------------------------------------- */ + +#ifdef MATHWORKS +#include "util.h" +#endif + +#ifdef MATLAB_MEX_FILE +#include "matrix.h" +#include "mex.h" +#endif + +/* ------------------------------------------------------------------------- */ +/* basic definitions */ +/* ------------------------------------------------------------------------- */ + +#ifdef FLIP +#undef FLIP +#endif + +#ifdef MAX +#undef MAX +#endif + +#ifdef MIN +#undef MIN +#endif + +#ifdef EMPTY +#undef EMPTY +#endif + +#ifdef GLOBAL +#undef GLOBAL +#endif + +#ifdef PRIVATE +#undef PRIVATE +#endif + +/* FLIP is a "negation about -1", and is used to mark an integer i that is + * normally non-negative. FLIP (EMPTY) is EMPTY. FLIP of a number > EMPTY + * is negative, and FLIP of a number < EMTPY is positive. FLIP (FLIP (i)) = i + * for all integers i. UNFLIP (i) is >= EMPTY. */ +#define EMPTY (-1) +#define FLIP(i) (-(i)-2) +#define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i)) + +/* for integer MAX/MIN, or for doubles when we don't care how NaN's behave: */ +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +/* logical expression of p implies q: */ +#define IMPLIES(p,q) (!(p) || (q)) + +/* Note that the IBM RS 6000 xlc predefines TRUE and FALSE in . */ +/* The Compaq Alpha also predefines TRUE and FALSE. */ +#ifdef TRUE +#undef TRUE +#endif +#ifdef FALSE +#undef FALSE +#endif + +#define TRUE (1) +#define FALSE (0) +#define PRIVATE static +#define GLOBAL +#define EMPTY (-1) + +/* Note that Linux's gcc 2.96 defines NULL as ((void *) 0), but other */ +/* compilers (even gcc 2.95.2 on Solaris) define NULL as 0 or (0). We */ +/* need to use the ANSI standard value of 0. */ +#ifdef NULL +#undef NULL +#endif + +#define NULL 0 + +/* ------------------------------------------------------------------------- */ +/* integer type for AMD: int or long */ +/* ------------------------------------------------------------------------- */ + +#if defined (DLONG) || defined (ZLONG) + +#define Int long +#define ID "%ld" +#define Int_MAX LONG_MAX +#define Int_MIN LONG_MIN + +#define AMD_order amd_l_order +#define AMD_defaults amd_l_defaults +#define AMD_control amd_l_control +#define AMD_info amd_l_info +#define AMD_1 amd_l1 +#define AMD_2 amd_l2 +#define AMD_valid amd_l_valid +#define AMD_aat amd_l_aat +#define AMD_postorder amd_l_postorder +#define AMD_post_tree amd_l_post_tree +#define AMD_dump amd_l_dump +#define AMD_debug amd_l_debug +#define AMD_debug_init amd_l_debug_init +#define AMD_wpreprocess amd_l_wpreprocess +#define AMD_preprocess amd_l_preprocess +#define AMD_preprocess_valid amd_l_preprocess_valid + +#else + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX +#define Int_MIN INT_MIN + +#define AMD_order amd_order +#define AMD_defaults amd_defaults +#define AMD_control amd_control +#define AMD_info amd_info +#define AMD_1 amd_1 +#define AMD_2 amd_2 +#define AMD_valid amd_valid +#define AMD_aat amd_aat +#define AMD_postorder amd_postorder +#define AMD_post_tree amd_post_tree +#define AMD_dump amd_dump +#define AMD_debug amd_debug +#define AMD_debug_init amd_debug_init +#define AMD_wpreprocess amd_wpreprocess +#define AMD_preprocess amd_preprocess +#define AMD_preprocess_valid amd_preprocess_valid + +#endif + +/* ========================================================================= */ +/* === Memory allocator ==================================================== */ +/* ========================================================================= */ + +/* The MATLAB mexFunction uses MATLAB's memory manager, while the C-callable */ +/* AMD routine uses the ANSI C malloc, free, and realloc routines. */ + +#ifndef ALLOCATE +#ifdef MATLAB_MEX_FILE +#define ALLOCATE mxMalloc +#define FREE mxFree +#else +#ifdef MATHWORKS +/* Compiling as a built-in routine. Since out-of-memory conditions are checked + * after every allocation, we can use ut* routines here. */ +#define ALLOCATE utMalloc +#define FREE utFree +#else +/* use the ANSI C memory allocation routines */ +#define ALLOCATE malloc +#define FREE free +#endif +#endif +#endif + + +/* ========================================================================= */ +/* === PRINTF macro ======================================================== */ +/* ========================================================================= */ + +/* All output goes through the PRINTF macro. */ + +#ifndef PRINTF +#ifdef MATLAB_MEX_FILE +#define PRINTF(params) { (void) mexPrintf params ; } +#else +#ifdef MATHWORKS +#define PRINTF(params) { (void) utPrintf params ; } +#else +#define PRINTF(params) { (void) printf params ; } +#endif +#endif +#endif + +/* ------------------------------------------------------------------------- */ +/* AMD routine definitions (user-callable) */ +/* ------------------------------------------------------------------------- */ + +#include "amd.h" + +/* ------------------------------------------------------------------------- */ +/* AMD routine definitions (not user-callable) */ +/* ------------------------------------------------------------------------- */ + +GLOBAL Int AMD_valid +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ] +) ; + +GLOBAL Int AMD_aat +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int Len [ ], + Int Tp [ ], + double Info [ ] +) ; + +GLOBAL void AMD_1 +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int P [ ], + Int Pinv [ ], + Int Len [ ], + Int slen, + Int S [ ], + double Control [ ], + double Info [ ] +) ; + +GLOBAL void AMD_2 ( + Int n, + Int Pe [ ], + Int Iw [ ], + Int Len [ ], + Int iwlen, + Int pfree, + Int Nv [ ], + Int Next [ ], + Int Last [ ], + Int Head [ ], + Int Elen [ ], + Int Degree [ ], + Int W [ ], + double Control [ ], + double Info [ ] +) ; + +GLOBAL void AMD_postorder +( + Int nn, + Int Parent [ ], + Int Npiv [ ], + Int Fsize [ ], + Int Order [ ], + Int Child [ ], + Int Sibling [ ], + Int Stack [ ] +) ; + +GLOBAL Int AMD_post_tree +( + Int root, + Int k, + Int Child [ ], + const Int Sibling [ ], + Int Order [ ], + Int Stack [ ] +#ifndef NDEBUG + , Int nn +#endif +) ; + +GLOBAL void AMD_wpreprocess +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int Rp [ ], + Int Ri [ ], + Int W [ ], + Int Flag [ ] +) ; + +GLOBAL Int AMD_preprocess_valid +( + Int n, + const Int Ap [ ], + const Int Ai [ ] +) ; + +/* ------------------------------------------------------------------------- */ +/* debugging definitions */ +/* ------------------------------------------------------------------------- */ + +/* from assert.h: assert macro */ +#if !defined (MATHWORKS) && !defined (MATLAB_MEX_FILE) +#include +#endif + +#ifndef NDEBUG + +GLOBAL Int AMD_debug ; + +GLOBAL void AMD_debug_init ( char *s ) ; + +GLOBAL void AMD_dump ( + Int n, + Int Pe [ ], + Int Iw [ ], + Int Len [ ], + Int iwlen, + Int pfree, + Int Nv [ ], + Int Next [ ], + Int Last [ ], + Int Head [ ], + Int Elen [ ], + Int Degree [ ], + Int W [ ], + Int nel +) ; + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef MATLAB_MEX_FILE +#define ASSERT(expression) (mxAssert ((expression), "")) +#else +#ifdef MATHWORKS +#define ASSERT(expression) (utAssert (expression)) +#else +#define ASSERT(expression) (assert (expression)) +#endif +#endif /* MATLAB_MEX_FILE */ + +#define AMD_DEBUG0(params) { PRINTF (params) ; } +#define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF (params) ; } +#define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF (params) ; } +#define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF (params) ; } +#define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF (params) ; } + +#else + +#define AMD_DEBUG0(params) +#define AMD_DEBUG1(params) +#define AMD_DEBUG2(params) +#define AMD_DEBUG3(params) +#define AMD_DEBUG4(params) + +#define ASSERT(expression) + +#endif diff --git a/liboctave/UMFPACK/AMD/Source/amd_order.c b/liboctave/UMFPACK/AMD/Source/amd_order.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_order.c @@ -0,0 +1,139 @@ +/* ========================================================================= */ +/* === AMD_order =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable AMD minimum degree ordering routine. See amd.h for + * documentation. + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_order +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int P [ ], + double Control [ ], + double Info [ ] +) +{ + Int slen, *Len, *S, nz, nzaat, i, *Pinv, info ; + +#ifndef NDEBUG + AMD_debug_init ("amd") ; +#endif + + /* clear the Info array, if it exists */ + info = Info != (double *) NULL ; + if (info) + { + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_N] = n ; + Info [AMD_STATUS] = AMD_OK ; + } + + /* make sure inputs exist and n is >= 0 */ + if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* arguments are invalid */ + } + + if (n == 0) + { + return (AMD_OK) ; /* n is 0 so there's nothing to do */ + } + + nz = Ap [n] ; + if (info) + { + Info [AMD_NZ] = nz ; + } + if (nz < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; + } + + /* Avoid integer overflow in memory size calculations. The space required + * by AMD is at most 2.4nz + 8n for S, and n for Len. + * Note nz - n <= nzaat <= 2*nz, below. */ + if ((2.4 * (double) nz + 8 * (double) n) > (double) Int_MAX / sizeof (Int)) + { + /* :: int overflow :: */ + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + + if (!AMD_valid (n, n, Ap, Ai)) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* matrix is invalid */ + } + + /* --------------------------------------------------------------------- */ + /* determine the symmetry and count off-diagonal nonzeros in A+A' */ + /* --------------------------------------------------------------------- */ + + /* allocate size-n integer workspace */ + Len = (Int *) ALLOCATE (n * sizeof (Int)) ; + if (!Len) + { + /* :: out of memory :: */ + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + nzaat = AMD_aat (n, Ap, Ai, Len, P, Info) ; + AMD_DEBUG1 (("nzaat: "ID"\n", nzaat)) ; + ASSERT (nz-n <= nzaat && nzaat <= 2*nz) ; + + /* --------------------------------------------------------------------- */ + /* allocate workspace for matrix, elbow room, and 7 size-n vectors */ + /* --------------------------------------------------------------------- */ + + slen = (nzaat + nzaat/5 + n) + 7*n ; + if (info) + { + /* memory usage (Len and S), in bytes. */ + Info [AMD_MEMORY] = ((double) slen + n) * sizeof (Int) ; + } + S = (Int *) ALLOCATE (slen * sizeof (Int)) ; + AMD_DEBUG1 ((" S "ID" Len "ID" n "ID" nzaat "ID" slen "ID"\n", + (Int) S, (Int) Len, n, nzaat, slen)) ; + if (S == (Int *) NULL) + { + /* :: out of memory :: */ + FREE (Len) ; + if (Info != (double *) NULL) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + + /* allocate space from S for Pinv */ + Pinv = S + slen - n ; + slen -= n ; + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_1 (n, Ap, Ai, P, Pinv, Len, slen, S, Control, Info) ; + + /* --------------------------------------------------------------------- */ + /* free the workspace */ + /* --------------------------------------------------------------------- */ + + FREE (Len) ; + FREE (S) ; + return (AMD_OK) ; /* successful ordering */ +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_post_tree.c b/liboctave/UMFPACK/AMD/Source/amd_post_tree.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_post_tree.c @@ -0,0 +1,121 @@ +/* ========================================================================= */ +/* === AMD_post_tree ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Post-ordering of a supernodal elimination tree. */ + +#include "amd_internal.h" + +GLOBAL Int AMD_post_tree +( + Int root, /* root of the tree */ + Int k, /* start numbering at k */ + Int Child [ ], /* input argument of size nn, undefined on + * output. Child [i] is the head of a link + * list of all nodes that are children of node + * i in the tree. */ + const Int Sibling [ ], /* input argument of size nn, not modified. + * If f is a node in the link list of the + * children of node i, then Sibling [f] is the + * next child of node i. + */ + Int Order [ ], /* output order, of size nn. Order [i] = k + * if node i is the kth node of the reordered + * tree. */ + Int Stack [ ] /* workspace of size nn */ +#ifndef NDEBUG + , Int nn /* nodes are in the range 0..nn-1. */ +#endif +) +{ + Int f, head, h, i ; + +#if 0 + /* --------------------------------------------------------------------- */ + /* recursive version (Stack [ ] is not used): */ + /* --------------------------------------------------------------------- */ + + /* this is simple, but can caouse stack overflow if nn is large */ + i = root ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; + } + Order [i] = k++ ; + return (k) ; +#endif + + /* --------------------------------------------------------------------- */ + /* non-recursive version, using an explicit stack */ + /* --------------------------------------------------------------------- */ + + /* push root on the stack */ + head = 0 ; + Stack [0] = root ; + + while (head >= 0) + { + /* get head of stack */ + ASSERT (head < nn) ; + i = Stack [head] ; + AMD_DEBUG1 (("head of stack "ID" \n", i)) ; + ASSERT (i >= 0 && i < nn) ; + + if (Child [i] != EMPTY) + { + /* the children of i are not yet ordered */ + /* push each child onto the stack in reverse order */ + /* so that small ones at the head of the list get popped first */ + /* and the biggest one at the end of the list gets popped last */ + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + head++ ; + ASSERT (head < nn) ; + ASSERT (f >= 0 && f < nn) ; + } + h = head ; + ASSERT (head < nn) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (h > 0) ; + Stack [h--] = f ; + AMD_DEBUG1 (("push "ID" on stack\n", f)) ; + ASSERT (f >= 0 && f < nn) ; + } + ASSERT (Stack [h] == i) ; + + /* delete child list so that i gets ordered next time we see it */ + Child [i] = EMPTY ; + } + else + { + /* the children of i (if there were any) are already ordered */ + /* remove i from the stack and order it. Front i is kth front */ + head-- ; + AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; + Order [i] = k++ ; + ASSERT (k <= nn) ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\nStack:")) ; + for (h = head ; h >= 0 ; h--) + { + Int j = Stack [h] ; + AMD_DEBUG1 ((" "ID, j)) ; + ASSERT (j >= 0 && j < nn) ; + } + AMD_DEBUG1 (("\n\n")) ; + ASSERT (head < nn) ; +#endif + + } + return (k) ; +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_postorder.c b/liboctave/UMFPACK/AMD/Source/amd_postorder.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_postorder.c @@ -0,0 +1,207 @@ +/* ========================================================================= */ +/* === AMD_postorder ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Perform a postordering (via depth-first search) of an assembly tree. */ + +#include "amd_internal.h" + +GLOBAL void AMD_postorder +( + /* inputs, not modified on output: */ + Int nn, /* nodes are in the range 0..nn-1 */ + Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */ + Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j, + * or zero if j is not a node. */ + Int Fsize [ ], /* Fsize [j]: size of node j */ + + /* output, not defined on input: */ + Int Order [ ], /* output post-order */ + + /* workspaces of size nn: */ + Int Child [ ], + Int Sibling [ ], + Int Stack [ ] +) +{ + Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; + + for (j = 0 ; j < nn ; j++) + { + Child [j] = EMPTY ; + Sibling [j] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* place the children in link lists - bigger elements tend to be last */ + /* --------------------------------------------------------------------- */ + + for (j = nn-1 ; j >= 0 ; j--) + { + if (Nv [j] > 0) + { + /* this is an element */ + parent = Parent [j] ; + if (parent != EMPTY) + { + /* place the element in link list of the children its parent */ + /* bigger elements will tend to be at the end of the list */ + Sibling [j] = Child [parent] ; + Child [parent] = j ; + } + } + } + +#ifndef NDEBUG + { + Int nels, ff, nchild ; + AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n")); + nels = 0 ; + for (j = 0 ; j < nn ; j++) + { + if (Nv [j] > 0) + { + AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID + " parent "ID" maxfr "ID"\n", j, nels, + Nv [j], Fsize [j], Parent [j], Fsize [j])) ; + /* this is an element */ + /* dump the link list of children */ + nchild = 0 ; + AMD_DEBUG1 ((" Children: ")) ; + for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) + { + AMD_DEBUG1 ((ID" ", ff)) ; + ASSERT (Parent [ff] == j) ; + nchild++ ; + ASSERT (nchild < nn) ; + } + AMD_DEBUG1 (("\n")) ; + parent = Parent [j] ; + if (parent != EMPTY) + { + ASSERT (Nv [parent] > 0) ; + } + nels++ ; + } + } + } + AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n" + "the biggest child last in each list:\n")) ; +#endif + + /* --------------------------------------------------------------------- */ + /* place the largest child last in the list of children for each node */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + if (Nv [i] > 0 && Child [i] != EMPTY) + { + +#ifndef NDEBUG + Int nchild ; + AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ; + nchild = 0 ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; + nchild++ ; + ASSERT (nchild <= nn) ; + } +#endif + + /* find the biggest element in the child list */ + fprev = EMPTY ; + maxfrsize = EMPTY ; + bigfprev = EMPTY ; + bigf = EMPTY ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + frsize = Fsize [f] ; + if (frsize >= maxfrsize) + { + /* this is the biggest seen so far */ + maxfrsize = frsize ; + bigfprev = fprev ; + bigf = f ; + } + fprev = f ; + } + ASSERT (bigf != EMPTY) ; + + fnext = Sibling [bigf] ; + + AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID + " fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ; + + if (fnext != EMPTY) + { + /* if fnext is EMPTY then bigf is already at the end of list */ + + if (bigfprev == EMPTY) + { + /* delete bigf from the element of the list */ + Child [i] = fnext ; + } + else + { + /* delete bigf from the middle of the list */ + Sibling [bigfprev] = fnext ; + } + + /* put bigf at the end of the list */ + Sibling [bigf] = EMPTY ; + ASSERT (Child [i] != EMPTY) ; + ASSERT (fprev != bigf) ; + ASSERT (fprev != EMPTY) ; + Sibling [fprev] = bigf ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; + ASSERT (Nv [f] > 0) ; + nchild-- ; + } + ASSERT (nchild == 0) ; +#endif + + } + } + + /* --------------------------------------------------------------------- */ + /* postorder the assembly tree */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + Order [i] = EMPTY ; + } + + k = 0 ; + + for (i = 0 ; i < nn ; i++) + { + if (Parent [i] == EMPTY && Nv [i] > 0) + { + AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ; + k = AMD_post_tree (i, k, Child, Sibling, Order, Stack +#ifndef NDEBUG + , nn +#endif + ) ; + } + } +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_preprocess.c b/liboctave/UMFPACK/AMD/Source/amd_preprocess.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_preprocess.c @@ -0,0 +1,225 @@ +/* ========================================================================= */ +/* === AMD_preprocess ====================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of + * a column-form matrix A, to obtain the matrix R. + * See amd.h for a complete description of AMD_preprocess + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_preprocess /* returns AMD_OK if input is OK, AMD_INVALID + * if the matrix is invalid, or AMD_OUT_OF_MEMORY + * if out of memory for the 2n workspace. */ +( + Int n, /* input matrix: A is n-by-n */ + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + + /* output matrix R: */ + Int Rp [ ], /* size n+1 */ + Int Ri [ ] /* size nz (or less, if duplicates present) */ +) +{ + /* --------------------------------------------------------------------- */ + /* local variables */ + /* --------------------------------------------------------------------- */ + + Int *Flag, *W ; + + /* --------------------------------------------------------------------- */ + /* check inputs (note: fewer restrictions than AMD_order) */ + /* --------------------------------------------------------------------- */ + + if (!AMD_preprocess_valid (n, Ap, Ai) || !Ri || !Rp) + { + return (AMD_INVALID) ; + } + + /* --------------------------------------------------------------------- */ + /* allocate workspace */ + /* --------------------------------------------------------------------- */ + + W = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ; + if (!W) + { + return (AMD_OUT_OF_MEMORY) ; + } + Flag = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ; + if (!Flag) + { + FREE (W) ; + return (AMD_OUT_OF_MEMORY) ; + } + + /* --------------------------------------------------------------------- */ + /* preprocess the matrix: sort, remove duplicates, and transpose */ + /* --------------------------------------------------------------------- */ + + AMD_wpreprocess (n, Ap, Ai, Rp, Ri, W, Flag) ; + + /* --------------------------------------------------------------------- */ + /* free the workspace */ + /* --------------------------------------------------------------------- */ + + FREE (W) ; + FREE (Flag) ; + return (AMD_OK) ; +} + + +/* ========================================================================= */ +/* === AMD_wpreprocess ===================================================== */ +/* ========================================================================= */ + +/* The AMD_wpreprocess routine is not user-callable. It does not check its + * input for errors or allocate workspace (that is done by the user-callable + * AMD_preprocess routine). It does handle the n=0 case. */ + +GLOBAL void AMD_wpreprocess +( + Int n, /* input matrix: A is n-by-n */ + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + + /* output matrix R: */ + Int Rp [ ], /* size n+1 */ + Int Ri [ ], /* size nz (or less, if duplicates present) */ + + Int W [ ], /* workspace of size n */ + Int Flag [ ] /* workspace of size n */ +) +{ + + /* --------------------------------------------------------------------- */ + /* local variables */ + /* --------------------------------------------------------------------- */ + + Int i, j, p, p2 ; + + /* --------------------------------------------------------------------- */ + /* count the entries in each row of A (excluding duplicates) */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ + Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ + } + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + W [i]++ ; /* one more entry in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + + /* --------------------------------------------------------------------- */ + /* compute the row pointers for R */ + /* --------------------------------------------------------------------- */ + + Rp [0] = 0 ; + for (i = 0 ; i < n ; i++) + { + Rp [i+1] = Rp [i] + W [i] ; + } + for (i = 0 ; i < n ; i++) + { + W [i] = Rp [i] ; + Flag [i] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* construct the row form matrix R */ + /* --------------------------------------------------------------------- */ + + /* R = row form of pattern of A */ + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + Ri [W [i]++] = j ; /* put col j in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + +#ifndef NDEBUG + for (j = 0 ; j < n ; j++) + { + ASSERT (W [j] == Rp [j+1]) ; + } + ASSERT (AMD_valid (n, n, Rp, Ri)) ; +#endif +} + + +/* ========================================================================= */ +/* === AMD_preprocess_valid ================================================ */ +/* ========================================================================= */ + +/* Not user-callable. Checks a matrix and returns TRUE if it is valid as input + * to AMD_wpreprocess, FALSE otherwise. */ + +GLOBAL Int AMD_preprocess_valid +( + Int n, + const Int Ap [ ], + const Int Ai [ ] +) +{ + Int i, j, p, nz ; + + if (n < 0 || !Ai || !Ap) + { + return (FALSE) ; + } + nz = Ap [n] ; + if (Ap [0] != 0 || nz < 0) + { + /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ + AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; + return (FALSE) ; + } + for (j = 0 ; j < n ; j++) + { + if (Ap [j] > Ap [j+1]) + { + /* column pointers must be ascending */ + AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; + return (FALSE) ; + } + } + for (p = 0 ; p < nz ; p++) + { + i = Ai [p] ; + AMD_DEBUG3 (("row: "ID"\n", i)) ; + if (i < 0 || i >= n) + { + /* row index out of range */ + AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)) ; + return (FALSE) ; + } + } + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/AMD/Source/amd_valid.c b/liboctave/UMFPACK/AMD/Source/amd_valid.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amd_valid.c @@ -0,0 +1,78 @@ +/* ========================================================================= */ +/* === AMD_valid =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ +/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Check if a column-form matrix is valid or not. The matrix A is + * n_row-by-n_col. The row indices of entries in column j are in + * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: + * + * n_row >= 0 + * n_col >= 0 + * nz = Ap [n_col] >= 0 number of entries in the matrix + * Ap [0] == 0 + * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. + * row indices in Ai [Ap [j] ... Ap [j+1]-1] must be sorted in ascending + * order, must be in the range 0 to n_row-1, and no duplicate entries + * can exist. + * + * Not user-callable. + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_valid +( + /* inputs, not modified on output: */ + Int n_row, /* A is n_row-by-n_col */ + Int n_col, + const Int Ap [ ], /* column pointers of A, of size n_col+1 */ + const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ +) +{ + Int nz, j, p1, p2, ilast, i, p ; + if (n_row < 0 || n_col < 0) + { + AMD_DEBUG0 (("n must be >= 0: "ID" "ID"\n", n_row, n_col)) ; + return (FALSE) ; + } + nz = Ap [n_col] ; + if (Ap [0] != 0 || nz < 0) + { + /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ + AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; + return (FALSE) ; + } + for (j = 0 ; j < n_col ; j++) + { + p1 = Ap [j] ; + p2 = Ap [j+1] ; + AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; + if (p1 > p2) + { + /* column pointers must be ascending */ + AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; + return (FALSE) ; + } + ilast = EMPTY ; + for (p = p1 ; p < p2 ; p++) + { + i = Ai [p] ; + AMD_DEBUG3 (("row: "ID"\n", i)) ; + if (i <= ilast || i >= n_row) + { + /* row index out of range, or unsorted */ + AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); + return (FALSE) ; + } + ilast = i ; + } + } + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/AMD/Source/amdbar.f b/liboctave/UMFPACK/AMD/Source/amdbar.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/AMD/Source/amdbar.f @@ -0,0 +1,1206 @@ +C----------------------------------------------------------------------- +C AMDBAR: approximate minimum degree, without aggressive absorption +C----------------------------------------------------------------------- + + SUBROUTINE AMDBAR + $ (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, + $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) + + INTEGER N, IWLEN, PFREE, NCMPA, IW (IWLEN), PE (N), + $ DEGREE (N), NV (N), NEXT (N), LAST (N), HEAD (N), + $ ELEN (N), W (N), LEN (N) + +C Given a representation of the nonzero pattern of a symmetric matrix, +C A, (excluding the diagonal) perform an approximate minimum +C (UMFPACK/MA38-style) degree ordering to compute a pivot order +C such that the introduction of nonzeros (fill-in) in the Cholesky +C factors A = LL^T are kept low. At each step, the pivot +C selected is the one with the minimum UMFPACK/MA38-style +C upper-bound on the external degree. +C +C This routine does not do aggresive absorption (as done by AMD). + +C ********************************************************************** +C ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** +C ********************************************************************** + +C References: +C +C [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern +C multifrontal method for sparse LU factorization", SIAM J. +C Matrix Analysis and Applications, vol. 18, no. 1, pp. +C 140-158. Discusses UMFPACK / MA38, which first introduced +C the approximate minimum degree used by this routine. +C +C [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An +C approximate degree ordering algorithm," SIAM J. Matrix +C Analysis and Applications, vol. 17, no. 4, pp. 886-905, +C 1996. Discusses AMD, AMDBAR, and MC47B. +C +C [3] Alan George and Joseph Liu, "The evolution of the minimum +C degree ordering algorithm," SIAM Review, vol. 31, no. 1, +C pp. 1-19, 1989. We list below the features mentioned in +C that paper that this code includes: +C +C mass elimination: +C Yes. MA27 relied on supervariable detection for mass +C elimination. +C indistinguishable nodes: +C Yes (we call these "supervariables"). This was also in +C the MA27 code - although we modified the method of +C detecting them (the previous hash was the true degree, +C which we no longer keep track of). A supervariable is +C a set of rows with identical nonzero pattern. All +C variables in a supervariable are eliminated together. +C Each supervariable has as its numerical name that of +C one of its variables (its principal variable). +C quotient graph representation: +C Yes. We use the term "element" for the cliques formed +C during elimination. This was also in the MA27 code. +C The algorithm can operate in place, but it will work +C more efficiently if given some "elbow room." +C element absorption: +C Yes. This was also in the MA27 code. +C external degree: +C Yes. The MA27 code was based on the true degree. +C incomplete degree update and multiple elimination: +C No. This was not in MA27, either. Our method of +C degree update within MC47B/BD is element-based, not +C variable-based. It is thus not well-suited for use +C with incomplete degree update or multiple elimination. + +C----------------------------------------------------------------------- +C Authors, and Copyright (C) 1995 by: +C Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & John K. Reid. +C +C Acknowledgements: +C This work (and the UMFPACK package) was supported by the +C National Science Foundation (ASC-9111263 and DMS-9223088). +C The UMFPACK/MA38 approximate degree update algorithm, the +C unsymmetric analog which forms the basis of MC47B/BD, was +C developed while Tim Davis was supported by CERFACS (Toulouse, +C France) in a post-doctoral position. +C +C Date: September, 1995 +C----------------------------------------------------------------------- + +C----------------------------------------------------------------------- +C INPUT ARGUMENTS (unaltered): +C----------------------------------------------------------------------- + +C n: The matrix order. +C +C Restriction: 1 .le. n .lt. (iovflo/2)-2, where iovflo is +C the largest positive integer that your computer can represent. + +C iwlen: The length of iw (1..iwlen). On input, the matrix is +C stored in iw (1..pfree-1). However, iw (1..iwlen) should be +C slightly larger than what is required to hold the matrix, at +C least iwlen .ge. pfree + n is recommended. Otherwise, +C excessive compressions will take place. +C *** We do not recommend running this algorithm with *** +C *** iwlen .lt. pfree + n. *** +C *** Better performance will be obtained if *** +C *** iwlen .ge. pfree + n *** +C *** or better yet *** +C *** iwlen .gt. 1.2 * pfree *** +C *** (where pfree is its value on input). *** +C The algorithm will not run at all if iwlen .lt. pfree-1. +C +C Restriction: iwlen .ge. pfree-1 + +C----------------------------------------------------------------------- +C INPUT/OUPUT ARGUMENTS: +C----------------------------------------------------------------------- + +C pe: On input, pe (i) is the index in iw of the start of row i, or +C zero if row i has no off-diagonal non-zeros. +C +C During execution, it is used for both supervariables and +C elements: +C +C * Principal supervariable i: index into iw of the +C description of supervariable i. A supervariable +C represents one or more rows of the matrix +C with identical nonzero pattern. +C * Non-principal supervariable i: if i has been absorbed +C into another supervariable j, then pe (i) = -j. +C That is, j has the same pattern as i. +C Note that j might later be absorbed into another +C supervariable j2, in which case pe (i) is still -j, +C and pe (j) = -j2. +C * Unabsorbed element e: the index into iw of the description +C of element e, if e has not yet been absorbed by a +C subsequent element. Element e is created when +C the supervariable of the same name is selected as +C the pivot. +C * Absorbed element e: if element e is absorbed into element +C e2, then pe (e) = -e2. This occurs when the pattern of +C e (that is, Le) is found to be a subset of the pattern +C of e2 (that is, Le2). If element e is "null" (it has +C no nonzeros outside its pivot block), then pe (e) = 0. +C +C On output, pe holds the assembly tree/forest, which implicitly +C represents a pivot order with identical fill-in as the actual +C order (via a depth-first search of the tree). +C +C On output: +C If nv (i) .gt. 0, then i represents a node in the assembly tree, +C and the parent of i is -pe (i), or zero if i is a root. +C If nv (i) = 0, then (i,-pe (i)) represents an edge in a +C subtree, the root of which is a node in the assembly tree. + +C pfree: On input the tail end of the array, iw (pfree..iwlen), +C is empty, and the matrix is stored in iw (1..pfree-1). +C During execution, additional data is placed in iw, and pfree +C is modified so that iw (pfree..iwlen) is always the unused part +C of iw. On output, pfree is set equal to the size of iw that +C would have been needed for no compressions to occur. If +C ncmpa is zero, then pfree (on output) is less than or equal to +C iwlen, and the space iw (pfree+1 ... iwlen) was not used. +C Otherwise, pfree (on output) is greater than iwlen, and all the +C memory in iw was used. + +C----------------------------------------------------------------------- +C INPUT/MODIFIED (undefined on output): +C----------------------------------------------------------------------- + +C len: On input, len (i) holds the number of entries in row i of the +C matrix, excluding the diagonal. The contents of len (1..n) +C are undefined on output. + +C iw: On input, iw (1..pfree-1) holds the description of each row i +C in the matrix. The matrix must be symmetric, and both upper +C and lower triangular parts must be present. The diagonal must +C not be present. Row i is held as follows: +C +C len (i): the length of the row i data structure +C iw (pe (i) ... pe (i) + len (i) - 1): +C the list of column indices for nonzeros +C in row i (simple supervariables), excluding +C the diagonal. All supervariables start with +C one row/column each (supervariable i is just +C row i). +C if len (i) is zero on input, then pe (i) is ignored +C on input. +C +C Note that the rows need not be in any particular order, +C and there may be empty space between the rows. +C +C During execution, the supervariable i experiences fill-in. +C This is represented by placing in i a list of the elements +C that cause fill-in in supervariable i: +C +C len (i): the length of supervariable i +C iw (pe (i) ... pe (i) + elen (i) - 1): +C the list of elements that contain i. This list +C is kept short by removing absorbed elements. +C iw (pe (i) + elen (i) ... pe (i) + len (i) - 1): +C the list of supervariables in i. This list +C is kept short by removing nonprincipal +C variables, and any entry j that is also +C contained in at least one of the elements +C (j in Le) in the list for i (e in row i). +C +C When supervariable i is selected as pivot, we create an +C element e of the same name (e=i): +C +C len (e): the length of element e +C iw (pe (e) ... pe (e) + len (e) - 1): +C the list of supervariables in element e. +C +C An element represents the fill-in that occurs when supervariable +C i is selected as pivot (which represents the selection of row i +C and all non-principal variables whose principal variable is i). +C We use the term Le to denote the set of all supervariables +C in element e. Absorbed supervariables and elements are pruned +C from these lists when computationally convenient. +C +C CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. +C The contents of iw are undefined on output. + +C----------------------------------------------------------------------- +C OUTPUT (need not be set on input): +C----------------------------------------------------------------------- + +C nv: During execution, abs (nv (i)) is equal to the number of rows +C that are represented by the principal supervariable i. If i is +C a nonprincipal variable, then nv (i) = 0. Initially, +C nv (i) = 1 for all i. nv (i) .lt. 0 signifies that i is a +C principal variable in the pattern Lme of the current pivot +C element me. On output, nv (e) holds the true degree of element +C e at the time it was created (including the diagonal part). + +C ncmpa: The number of times iw was compressed. If this is +C excessive, then the execution took longer than what could have +C been. To reduce ncmpa, try increasing iwlen to be 10% or 20% +C larger than the value of pfree on input (or at least +C iwlen .ge. pfree + n). The fastest performance will be +C obtained when ncmpa is returned as zero. If iwlen is set to +C the value returned by pfree on *output*, then no compressions +C will occur. + +C elen: See the description of iw above. At the start of execution, +C elen (i) is set to zero. During execution, elen (i) is the +C number of elements in the list for supervariable i. When e +C becomes an element, elen (e) = -nel is set, where nel is the +C current step of factorization. elen (i) = 0 is done when i +C becomes nonprincipal. +C +C For variables, elen (i) .ge. 0 holds until just before the +C permutation vectors are computed. For elements, +C elen (e) .lt. 0 holds. +C +C On output elen (1..n) holds the inverse permutation (the same +C as the 'INVP' argument in Sparspak). That is, if k = elen (i), +C then row i is the kth pivot row. Row i of A appears as the +C (elen(i))-th row in the permuted matrix, PAP^T. + +C last: In a degree list, last (i) is the supervariable preceding i, +C or zero if i is the head of the list. In a hash bucket, +C last (i) is the hash key for i. last (head (hash)) is also +C used as the head of a hash bucket if head (hash) contains a +C degree list (see head, below). +C +C On output, last (1..n) holds the permutation (the same as the +C 'PERM' argument in Sparspak). That is, if i = last (k), then +C row i is the kth pivot row. Row last (k) of A is the k-th row +C in the permuted matrix, PAP^T. + +C----------------------------------------------------------------------- +C LOCAL (not input or output - used only during execution): +C----------------------------------------------------------------------- + +C degree: If i is a supervariable, then degree (i) holds the +C current approximation of the external degree of row i (an upper +C bound). The external degree is the number of nonzeros in row i, +C minus abs (nv (i)) (the diagonal part). The bound is equal to +C the external degree if elen (i) is less than or equal to two. +C +C We also use the term "external degree" for elements e to refer +C to |Le \ Lme|. If e is an element, then degree (e) holds |Le|, +C which is the degree of the off-diagonal part of the element e +C (not including the diagonal part). + +C head: head is used for degree lists. head (deg) is the first +C supervariable in a degree list (all supervariables i in a +C degree list deg have the same approximate degree, namely, +C deg = degree (i)). If the list deg is empty then +C head (deg) = 0. +C +C During supervariable detection head (hash) also serves as a +C pointer to a hash bucket. +C If head (hash) .gt. 0, there is a degree list of degree hash. +C The hash bucket head pointer is last (head (hash)). +C If head (hash) = 0, then the degree list and hash bucket are +C both empty. +C If head (hash) .lt. 0, then the degree list is empty, and +C -head (hash) is the head of the hash bucket. +C After supervariable detection is complete, all hash buckets +C are empty, and the (last (head (hash)) = 0) condition is +C restored for the non-empty degree lists. + +C next: next (i) is the supervariable following i in a link list, or +C zero if i is the last in the list. Used for two kinds of +C lists: degree lists and hash buckets (a supervariable can be +C in only one kind of list at a time). + +C w: The flag array w determines the status of elements and +C variables, and the external degree of elements. +C +C for elements: +C if w (e) = 0, then the element e is absorbed +C if w (e) .ge. wflg, then w (e) - wflg is the size of +C the set |Le \ Lme|, in terms of nonzeros (the +C sum of abs (nv (i)) for each principal variable i that +C is both in the pattern of element e and NOT in the +C pattern of the current pivot element, me). +C if wflg .gt. w (e) .gt. 0, then e is not absorbed and has +C not yet been seen in the scan of the element lists in +C the computation of |Le\Lme| in loop 150 below. +C +C for variables: +C during supervariable detection, if w (j) .ne. wflg then j is +C not in the pattern of variable i +C +C The w array is initialized by setting w (i) = 1 for all i, +C and by setting wflg = 2. It is reinitialized if wflg becomes +C too large (to ensure that wflg+n does not cause integer +C overflow). + +C----------------------------------------------------------------------- +C LOCAL INTEGERS: +C----------------------------------------------------------------------- + + INTEGER DEG, DEGME, DMAX, E, ELENME, ELN, HASH, HMOD, I, + $ ILAST, INEXT, J, JLAST, JNEXT, K, KNT1, KNT2, KNT3, + $ LENJ, LN, MAXMEM, ME, MEM, MINDEG, NEL, NEWMEM, + $ NLEFT, NVI, NVJ, NVPIV, SLENME, WE, WFLG, WNVI, X + +C deg: the degree of a variable or element +C degme: size, |Lme|, of the current element, me (= degree (me)) +C dext: external degree, |Le \ Lme|, of some element e +C dmax: largest |Le| seen so far +C e: an element +C elenme: the length, elen (me), of element list of pivotal var. +C eln: the length, elen (...), of an element list +C hash: the computed value of the hash function +C hmod: the hash function is computed modulo hmod = max (1,n-1) +C i: a supervariable +C ilast: the entry in a link list preceding i +C inext: the entry in a link list following i +C j: a supervariable +C jlast: the entry in a link list preceding j +C jnext: the entry in a link list, or path, following j +C k: the pivot order of an element or variable +C knt1: loop counter used during element construction +C knt2: loop counter used during element construction +C knt3: loop counter used during compression +C lenj: len (j) +C ln: length of a supervariable list +C maxmem: amount of memory needed for no compressions +C me: current supervariable being eliminated, and the +C current element created by eliminating that +C supervariable +C mem: memory in use assuming no compressions have occurred +C mindeg: current minimum degree +C nel: number of pivots selected so far +C newmem: amount of new memory needed for current pivot element +C nleft: n - nel, the number of nonpivotal rows/columns remaining +C nvi: the number of variables in a supervariable i (= nv (i)) +C nvj: the number of variables in a supervariable j (= nv (j)) +C nvpiv: number of pivots in current element +C slenme: number of variables in variable list of pivotal variable +C we: w (e) +C wflg: used for flagging the w array. See description of iw. +C wnvi: wflg - nv (i) +C x: either a supervariable or an element + +C----------------------------------------------------------------------- +C LOCAL POINTERS: +C----------------------------------------------------------------------- + + INTEGER P, P1, P2, P3, PDST, PEND, PJ, PME, PME1, PME2, PN, PSRC + +C Any parameter (pe (...) or pfree) or local variable +C starting with "p" (for Pointer) is an index into iw, +C and all indices into iw use variables starting with +C "p." The only exception to this rule is the iwlen +C input argument. + +C p: pointer into lots of things +C p1: pe (i) for some variable i (start of element list) +C p2: pe (i) + elen (i) - 1 for some var. i (end of el. list) +C p3: index of first supervariable in clean list +C pdst: destination pointer, for compression +C pend: end of memory to compress +C pj: pointer into an element or variable +C pme: pointer into the current element (pme1...pme2) +C pme1: the current element, me, is stored in iw (pme1...pme2) +C pme2: the end of the current element +C pn: pointer into a "clean" variable, also used to compress +C psrc: source pointer, for compression + +C----------------------------------------------------------------------- +C FUNCTIONS CALLED: +C----------------------------------------------------------------------- + + INTRINSIC MAX, MIN, MOD + +C======================================================================= +C INITIALIZATIONS +C======================================================================= + + WFLG = 2 + MINDEG = 1 + NCMPA = 0 + NEL = 0 + HMOD = MAX (1, N-1) + DMAX = 0 + MEM = PFREE - 1 + MAXMEM = MEM + ME = 0 + + DO 10 I = 1, N + LAST (I) = 0 + HEAD (I) = 0 + NV (I) = 1 + W (I) = 1 + ELEN (I) = 0 + DEGREE (I) = LEN (I) +10 CONTINUE + +C ---------------------------------------------------------------- +C initialize degree lists and eliminate rows with no off-diag. nz. +C ---------------------------------------------------------------- + + DO 20 I = 1, N + + DEG = DEGREE (I) + + IF (DEG .GT. 0) THEN + +C ---------------------------------------------------------- +C place i in the degree list corresponding to its degree +C ---------------------------------------------------------- + + INEXT = HEAD (DEG) + IF (INEXT .NE. 0) LAST (INEXT) = I + NEXT (I) = INEXT + HEAD (DEG) = I + + ELSE + +C ---------------------------------------------------------- +C we have a variable that can be eliminated at once because +C there is no off-diagonal non-zero in its row. +C ---------------------------------------------------------- + + NEL = NEL + 1 + ELEN (I) = -NEL + PE (I) = 0 + W (I) = 0 + + ENDIF + +20 CONTINUE + +C======================================================================= +C WHILE (selecting pivots) DO +C======================================================================= + +30 CONTINUE + IF (NEL .LT. N) THEN + +C======================================================================= +C GET PIVOT OF MINIMUM DEGREE +C======================================================================= + +C ------------------------------------------------------------- +C find next supervariable for elimination +C ------------------------------------------------------------- + + DO 40 DEG = MINDEG, N + ME = HEAD (DEG) + IF (ME .GT. 0) GOTO 50 +40 CONTINUE +50 CONTINUE + MINDEG = DEG + +C ------------------------------------------------------------- +C remove chosen variable from link list +C ------------------------------------------------------------- + + INEXT = NEXT (ME) + IF (INEXT .NE. 0) LAST (INEXT) = 0 + HEAD (DEG) = INEXT + +C ------------------------------------------------------------- +C me represents the elimination of pivots nel+1 to nel+nv(me). +C place me itself as the first in this set. It will be moved +C to the nel+nv(me) position when the permutation vectors are +C computed. +C ------------------------------------------------------------- + + ELENME = ELEN (ME) + ELEN (ME) = - (NEL + 1) + NVPIV = NV (ME) + NEL = NEL + NVPIV + +C======================================================================= +C CONSTRUCT NEW ELEMENT +C======================================================================= + +C ------------------------------------------------------------- +C At this point, me is the pivotal supervariable. It will be +C converted into the current element. Scan list of the +C pivotal supervariable, me, setting tree pointers and +C constructing new list of supervariables for the new element, +C me. p is a pointer to the current position in the old list. +C ------------------------------------------------------------- + +C flag the variable "me" as being in Lme by negating nv (me) + NV (ME) = -NVPIV + DEGME = 0 + + IF (ELENME .EQ. 0) THEN + +C ---------------------------------------------------------- +C construct the new element in place +C ---------------------------------------------------------- + + PME1 = PE (ME) + PME2 = PME1 - 1 + + DO 60 P = PME1, PME1 + LEN (ME) - 1 + I = IW (P) + NVI = NV (I) + IF (NVI .GT. 0) THEN + +C ---------------------------------------------------- +C i is a principal variable not yet placed in Lme. +C store i in new list +C ---------------------------------------------------- + + DEGME = DEGME + NVI +C flag i as being in Lme by negating nv (i) + NV (I) = -NVI + PME2 = PME2 + 1 + IW (PME2) = I + +C ---------------------------------------------------- +C remove variable i from degree list. +C ---------------------------------------------------- + + ILAST = LAST (I) + INEXT = NEXT (I) + IF (INEXT .NE. 0) LAST (INEXT) = ILAST + IF (ILAST .NE. 0) THEN + NEXT (ILAST) = INEXT + ELSE +C i is at the head of the degree list + HEAD (DEGREE (I)) = INEXT + ENDIF + + ENDIF +60 CONTINUE +C this element takes no new memory in iw: + NEWMEM = 0 + + ELSE + +C ---------------------------------------------------------- +C construct the new element in empty space, iw (pfree ...) +C ---------------------------------------------------------- + + P = PE (ME) + PME1 = PFREE + SLENME = LEN (ME) - ELENME + + DO 120 KNT1 = 1, ELENME + 1 + + IF (KNT1 .GT. ELENME) THEN +C search the supervariables in me. + E = ME + PJ = P + LN = SLENME + ELSE +C search the elements in me. + E = IW (P) + P = P + 1 + PJ = PE (E) + LN = LEN (E) + ENDIF + +C ------------------------------------------------------- +C search for different supervariables and add them to the +C new list, compressing when necessary. this loop is +C executed once for each element in the list and once for +C all the supervariables in the list. +C ------------------------------------------------------- + + DO 110 KNT2 = 1, LN + I = IW (PJ) + PJ = PJ + 1 + NVI = NV (I) + IF (NVI .GT. 0) THEN + +C ------------------------------------------------- +C compress iw, if necessary +C ------------------------------------------------- + + IF (PFREE .GT. IWLEN) THEN +C prepare for compressing iw by adjusting +C pointers and lengths so that the lists being +C searched in the inner and outer loops contain +C only the remaining entries. + + PE (ME) = P + LEN (ME) = LEN (ME) - KNT1 + IF (LEN (ME) .EQ. 0) THEN +C nothing left of supervariable me + PE (ME) = 0 + ENDIF + PE (E) = PJ + LEN (E) = LN - KNT2 + IF (LEN (E) .EQ. 0) THEN +C nothing left of element e + PE (E) = 0 + ENDIF + + NCMPA = NCMPA + 1 +C store first item in pe +C set first entry to -item + DO 70 J = 1, N + PN = PE (J) + IF (PN .GT. 0) THEN + PE (J) = IW (PN) + IW (PN) = -J + ENDIF +70 CONTINUE + +C psrc/pdst point to source/destination + PDST = 1 + PSRC = 1 + PEND = PME1 - 1 + +C while loop: +80 CONTINUE + IF (PSRC .LE. PEND) THEN +C search for next negative entry + J = -IW (PSRC) + PSRC = PSRC + 1 + IF (J .GT. 0) THEN + IW (PDST) = PE (J) + PE (J) = PDST + PDST = PDST + 1 +C copy from source to destination + LENJ = LEN (J) + DO 90 KNT3 = 0, LENJ - 2 + IW (PDST + KNT3) = IW (PSRC + KNT3) +90 CONTINUE + PDST = PDST + LENJ - 1 + PSRC = PSRC + LENJ - 1 + ENDIF + GOTO 80 + ENDIF + +C move the new partially-constructed element + P1 = PDST + DO 100 PSRC = PME1, PFREE - 1 + IW (PDST) = IW (PSRC) + PDST = PDST + 1 +100 CONTINUE + PME1 = P1 + PFREE = PDST + PJ = PE (E) + P = PE (ME) + ENDIF + +C ------------------------------------------------- +C i is a principal variable not yet placed in Lme +C store i in new list +C ------------------------------------------------- + + DEGME = DEGME + NVI +C flag i as being in Lme by negating nv (i) + NV (I) = -NVI + IW (PFREE) = I + PFREE = PFREE + 1 + +C ------------------------------------------------- +C remove variable i from degree link list +C ------------------------------------------------- + + ILAST = LAST (I) + INEXT = NEXT (I) + IF (INEXT .NE. 0) LAST (INEXT) = ILAST + IF (ILAST .NE. 0) THEN + NEXT (ILAST) = INEXT + ELSE +C i is at the head of the degree list + HEAD (DEGREE (I)) = INEXT + ENDIF + + ENDIF +110 CONTINUE + + IF (E .NE. ME) THEN +C set tree pointer and flag to indicate element e is +C absorbed into new element me (the parent of e is me) + PE (E) = -ME + W (E) = 0 + ENDIF +120 CONTINUE + + PME2 = PFREE - 1 +C this element takes newmem new memory in iw (possibly zero) + NEWMEM = PFREE - PME1 + MEM = MEM + NEWMEM + MAXMEM = MAX (MAXMEM, MEM) + ENDIF + +C ------------------------------------------------------------- +C me has now been converted into an element in iw (pme1..pme2) +C ------------------------------------------------------------- + +C degme holds the external degree of new element + DEGREE (ME) = DEGME + PE (ME) = PME1 + LEN (ME) = PME2 - PME1 + 1 + +C ------------------------------------------------------------- +C make sure that wflg is not too large. With the current +C value of wflg, wflg+n must not cause integer overflow +C ------------------------------------------------------------- + + IF (WFLG + N .LE. WFLG) THEN + DO 130 X = 1, N + IF (W (X) .NE. 0) W (X) = 1 +130 CONTINUE + WFLG = 2 + ENDIF + +C======================================================================= +C COMPUTE (w (e) - wflg) = |Le\Lme| FOR ALL ELEMENTS +C======================================================================= + +C ------------------------------------------------------------- +C Scan 1: compute the external degrees of previous elements +C with respect to the current element. That is: +C (w (e) - wflg) = |Le \ Lme| +C for each element e that appears in any supervariable in Lme. +C The notation Le refers to the pattern (list of +C supervariables) of a previous element e, where e is not yet +C absorbed, stored in iw (pe (e) + 1 ... pe (e) + iw (pe (e))). +C The notation Lme refers to the pattern of the current element +C (stored in iw (pme1..pme2)). If (w (e) - wflg) becomes +C zero, then the element e will be absorbed in scan 2. +C ------------------------------------------------------------- + + DO 150 PME = PME1, PME2 + I = IW (PME) + ELN = ELEN (I) + IF (ELN .GT. 0) THEN +C note that nv (i) has been negated to denote i in Lme: + NVI = -NV (I) + WNVI = WFLG - NVI + DO 140 P = PE (I), PE (I) + ELN - 1 + E = IW (P) + WE = W (E) + IF (WE .GE. WFLG) THEN +C unabsorbed element e has been seen in this loop + WE = WE - NVI + ELSE IF (WE .NE. 0) THEN +C e is an unabsorbed element +C this is the first we have seen e in all of Scan 1 + WE = DEGREE (E) + WNVI + ENDIF + W (E) = WE +140 CONTINUE + ENDIF +150 CONTINUE + +C======================================================================= +C DEGREE UPDATE AND ELEMENT ABSORPTION +C======================================================================= + +C ------------------------------------------------------------- +C Scan 2: for each i in Lme, sum up the degree of Lme (which +C is degme), plus the sum of the external degrees of each Le +C for the elements e appearing within i, plus the +C supervariables in i. Place i in hash list. +C ------------------------------------------------------------- + + DO 180 PME = PME1, PME2 + I = IW (PME) + P1 = PE (I) + P2 = P1 + ELEN (I) - 1 + PN = P1 + HASH = 0 + DEG = 0 + +C ---------------------------------------------------------- +C scan the element list associated with supervariable i +C ---------------------------------------------------------- + +C UMFPACK/MA38-style approximate degree: + DO 160 P = P1, P2 + E = IW (P) + WE = W (E) + IF (WE .NE. 0) THEN +C e is an unabsorbed element + DEG = DEG + WE - WFLG + IW (PN) = E + PN = PN + 1 + HASH = HASH + E + ENDIF +160 CONTINUE + +C count the number of elements in i (including me): + ELEN (I) = PN - P1 + 1 + +C ---------------------------------------------------------- +C scan the supervariables in the list associated with i +C ---------------------------------------------------------- + + P3 = PN + DO 170 P = P2 + 1, P1 + LEN (I) - 1 + J = IW (P) + NVJ = NV (J) + IF (NVJ .GT. 0) THEN +C j is unabsorbed, and not in Lme. +C add to degree and add to new list + DEG = DEG + NVJ + IW (PN) = J + PN = PN + 1 + HASH = HASH + J + ENDIF +170 CONTINUE + +C ---------------------------------------------------------- +C update the degree and check for mass elimination +C ---------------------------------------------------------- + + IF (ELEN (I) .EQ. 1 .AND. P3 .EQ. PN) THEN + +C ------------------------------------------------------- +C mass elimination +C ------------------------------------------------------- + +C There is nothing left of this node except for an +C edge to the current pivot element. elen (i) is 1, +C and there are no variables adjacent to node i. +C Absorb i into the current pivot element, me. + + PE (I) = -ME + NVI = -NV (I) + DEGME = DEGME - NVI + NVPIV = NVPIV + NVI + NEL = NEL + NVI + NV (I) = 0 + ELEN (I) = 0 + + ELSE + +C ------------------------------------------------------- +C update the upper-bound degree of i +C ------------------------------------------------------- + +C the following degree does not yet include the size +C of the current element, which is added later: + DEGREE (I) = MIN (DEGREE (I), DEG) + +C ------------------------------------------------------- +C add me to the list for i +C ------------------------------------------------------- + +C move first supervariable to end of list + IW (PN) = IW (P3) +C move first element to end of element part of list + IW (P3) = IW (P1) +C add new element to front of list. + IW (P1) = ME +C store the new length of the list in len (i) + LEN (I) = PN - P1 + 1 + +C ------------------------------------------------------- +C place in hash bucket. Save hash key of i in last (i). +C ------------------------------------------------------- + + HASH = MOD (HASH, HMOD) + 1 + J = HEAD (HASH) + IF (J .LE. 0) THEN +C the degree list is empty, hash head is -j + NEXT (I) = -J + HEAD (HASH) = -I + ELSE +C degree list is not empty +C use last (head (hash)) as hash head + NEXT (I) = LAST (J) + LAST (J) = I + ENDIF + LAST (I) = HASH + ENDIF +180 CONTINUE + + DEGREE (ME) = DEGME + +C ------------------------------------------------------------- +C Clear the counter array, w (...), by incrementing wflg. +C ------------------------------------------------------------- + + DMAX = MAX (DMAX, DEGME) + WFLG = WFLG + DMAX + +C make sure that wflg+n does not cause integer overflow + IF (WFLG + N .LE. WFLG) THEN + DO 190 X = 1, N + IF (W (X) .NE. 0) W (X) = 1 +190 CONTINUE + WFLG = 2 + ENDIF +C at this point, w (1..n) .lt. wflg holds + +C======================================================================= +C SUPERVARIABLE DETECTION +C======================================================================= + + DO 250 PME = PME1, PME2 + I = IW (PME) + IF (NV (I) .LT. 0) THEN +C i is a principal variable in Lme + +C ------------------------------------------------------- +C examine all hash buckets with 2 or more variables. We +C do this by examing all unique hash keys for super- +C variables in the pattern Lme of the current element, me +C ------------------------------------------------------- + + HASH = LAST (I) +C let i = head of hash bucket, and empty the hash bucket + J = HEAD (HASH) + IF (J .EQ. 0) GOTO 250 + IF (J .LT. 0) THEN +C degree list is empty + I = -J + HEAD (HASH) = 0 + ELSE +C degree list is not empty, restore last () of head + I = LAST (J) + LAST (J) = 0 + ENDIF + IF (I .EQ. 0) GOTO 250 + +C while loop: +200 CONTINUE + IF (NEXT (I) .NE. 0) THEN + +C ---------------------------------------------------- +C this bucket has one or more variables following i. +C scan all of them to see if i can absorb any entries +C that follow i in hash bucket. Scatter i into w. +C ---------------------------------------------------- + + LN = LEN (I) + ELN = ELEN (I) +C do not flag the first element in the list (me) + DO 210 P = PE (I) + 1, PE (I) + LN - 1 + W (IW (P)) = WFLG +210 CONTINUE + +C ---------------------------------------------------- +C scan every other entry j following i in bucket +C ---------------------------------------------------- + + JLAST = I + J = NEXT (I) + +C while loop: +220 CONTINUE + IF (J .NE. 0) THEN + +C ------------------------------------------------- +C check if j and i have identical nonzero pattern +C ------------------------------------------------- + + IF (LEN (J) .NE. LN) THEN +C i and j do not have same size data structure + GOTO 240 + ENDIF + IF (ELEN (J) .NE. ELN) THEN +C i and j do not have same number of adjacent el + GOTO 240 + ENDIF +C do not flag the first element in the list (me) + DO 230 P = PE (J) + 1, PE (J) + LN - 1 + IF (W (IW (P)) .NE. WFLG) THEN +C an entry (iw(p)) is in j but not in i + GOTO 240 + ENDIF +230 CONTINUE + +C ------------------------------------------------- +C found it! j can be absorbed into i +C ------------------------------------------------- + + PE (J) = -I +C both nv (i) and nv (j) are negated since they +C are in Lme, and the absolute values of each +C are the number of variables in i and j: + NV (I) = NV (I) + NV (J) + NV (J) = 0 + ELEN (J) = 0 +C delete j from hash bucket + J = NEXT (J) + NEXT (JLAST) = J + GOTO 220 + +C ------------------------------------------------- +240 CONTINUE +C j cannot be absorbed into i +C ------------------------------------------------- + + JLAST = J + J = NEXT (J) + GOTO 220 + ENDIF + +C ---------------------------------------------------- +C no more variables can be absorbed into i +C go to next i in bucket and clear flag array +C ---------------------------------------------------- + + WFLG = WFLG + 1 + I = NEXT (I) + IF (I .NE. 0) GOTO 200 + ENDIF + ENDIF +250 CONTINUE + +C======================================================================= +C RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVAR. FROM ELEMENT +C======================================================================= + + P = PME1 + NLEFT = N - NEL + DO 260 PME = PME1, PME2 + I = IW (PME) + NVI = -NV (I) + IF (NVI .GT. 0) THEN +C i is a principal variable in Lme +C restore nv (i) to signify that i is principal + NV (I) = NVI + +C ------------------------------------------------------- +C compute the external degree (add size of current elem) +C ------------------------------------------------------- + + DEG = MAX (1, MIN (DEGREE (I) + DEGME-NVI, NLEFT-NVI)) + +C ------------------------------------------------------- +C place the supervariable at the head of the degree list +C ------------------------------------------------------- + + INEXT = HEAD (DEG) + IF (INEXT .NE. 0) LAST (INEXT) = I + NEXT (I) = INEXT + LAST (I) = 0 + HEAD (DEG) = I + +C ------------------------------------------------------- +C save the new degree, and find the minimum degree +C ------------------------------------------------------- + + MINDEG = MIN (MINDEG, DEG) + DEGREE (I) = DEG + +C ------------------------------------------------------- +C place the supervariable in the element pattern +C ------------------------------------------------------- + + IW (P) = I + P = P + 1 + ENDIF +260 CONTINUE + +C======================================================================= +C FINALIZE THE NEW ELEMENT +C======================================================================= + + NV (ME) = NVPIV + DEGME +C nv (me) is now the degree of pivot (including diagonal part) +C save the length of the list for the new element me + LEN (ME) = P - PME1 + IF (LEN (ME) .EQ. 0) THEN +C there is nothing left of the current pivot element + PE (ME) = 0 + W (ME) = 0 + ENDIF + IF (NEWMEM .NE. 0) THEN +C element was not constructed in place: deallocate part +C of it (final size is less than or equal to newmem, +C since newly nonprincipal variables have been removed). + PFREE = P + MEM = MEM - NEWMEM + LEN (ME) + ENDIF + +C======================================================================= +C END WHILE (selecting pivots) + GOTO 30 + ENDIF +C======================================================================= + +C======================================================================= +C COMPUTE THE PERMUTATION VECTORS +C======================================================================= + +C ---------------------------------------------------------------- +C The time taken by the following code is O(n). At this +C point, elen (e) = -k has been done for all elements e, +C and elen (i) = 0 has been done for all nonprincipal +C variables i. At this point, there are no principal +C supervariables left, and all elements are absorbed. +C ---------------------------------------------------------------- + +C ---------------------------------------------------------------- +C compute the ordering of unordered nonprincipal variables +C ---------------------------------------------------------------- + + DO 290 I = 1, N + IF (ELEN (I) .EQ. 0) THEN + +C ---------------------------------------------------------- +C i is an un-ordered row. Traverse the tree from i until +C reaching an element, e. The element, e, was the +C principal supervariable of i and all nodes in the path +C from i to when e was selected as pivot. +C ---------------------------------------------------------- + + J = -PE (I) +C while (j is a variable) do: +270 CONTINUE + IF (ELEN (J) .GE. 0) THEN + J = -PE (J) + GOTO 270 + ENDIF + E = J + +C ---------------------------------------------------------- +C get the current pivot ordering of e +C ---------------------------------------------------------- + + K = -ELEN (E) + +C ---------------------------------------------------------- +C traverse the path again from i to e, and compress the +C path (all nodes point to e). Path compression allows +C this code to compute in O(n) time. Order the unordered +C nodes in the path, and place the element e at the end. +C ---------------------------------------------------------- + + J = I +C while (j is a variable) do: +280 CONTINUE + IF (ELEN (J) .GE. 0) THEN + JNEXT = -PE (J) + PE (J) = -E + IF (ELEN (J) .EQ. 0) THEN +C j is an unordered row + ELEN (J) = K + K = K + 1 + ENDIF + J = JNEXT + GOTO 280 + ENDIF +C leave elen (e) negative, so we know it is an element + ELEN (E) = -K + ENDIF +290 CONTINUE + +C ---------------------------------------------------------------- +C reset the inverse permutation (elen (1..n)) to be positive, +C and compute the permutation (last (1..n)). +C ---------------------------------------------------------------- + + DO 300 I = 1, N + K = ABS (ELEN (I)) + LAST (K) = I + ELEN (I) = K +300 CONTINUE + +C======================================================================= +C RETURN THE MEMORY USAGE IN IW +C======================================================================= + +C If maxmem is less than or equal to iwlen, then no compressions +C occurred, and iw (maxmem+1 ... iwlen) was unused. Otherwise +C compressions did occur, and iwlen would have had to have been +C greater than or equal to maxmem for no compressions to occur. +C Return the value of maxmem in the pfree argument. + + PFREE = MAXMEM + + RETURN + END + diff --git a/liboctave/UMFPACK/README.txt b/liboctave/UMFPACK/README.txt new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/README.txt @@ -0,0 +1,5 @@ +UMFPACK v4.4 and AMD v1.1. + +See UMFPACK/README.txt and AMD/README.txt for details. Documention is in +UMFPACK/Doc and AMD/Doc. + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/HB/arc130.rua b/liboctave/UMFPACK/UMFPACK/Demo/HB/arc130.rua new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/HB/arc130.rua @@ -0,0 +1,506 @@ +1UNSYMMETRIC MATRIX FROM LASER PROBLEM. A.R.CURTIS, OCT 1974 ARC130 + 502 9 65 428 0 +RUA 130 130 1282 0 +(16I5) (20I4) (1P3D24.15) + 1 41 102 163 224 285 325 344 363 380 397 413 423 433 443 452 + 461 471 595 597 721 722 723 724 725 726 732 737 744 750 755 761 + 766 773 779 785 791 796 801 806 812 818 824 830 836 841 847 852 + 858 863 868 874 879 884 889 896 903 908 914 919 925 931 936 943 + 948 953 959 964 971 976 981 986 991 997 1002 1008 1013 1018 1023 1028 + 1033 1038 1043 1048 1053 1058 1063 1068 1073 1078 1083 1088 1093 1098 1103 1108 + 1113 1118 1123 1128 1133 1138 1143 1148 1153 1158 1163 1168 1173 1178 1183 1188 + 1193 1198 1203 1208 1213 1218 1223 1228 1233 1238 1243 1248 1253 1258 1263 1268 + 1273 1278 1283 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 19 20 26 + 31 36 41 46 51 56 61 66 71 76 81 86 91 96 101 106 111 116 121 126 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 19 20 26 + 27 31 32 36 37 41 42 46 47 51 52 56 57 61 62 66 67 71 72 76 + 77 81 82 86 87 91 92 96 97 101 102 106 107 111 112 116 117 121 122 126 + 127 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 19 20 + 27 28 32 33 37 38 42 43 47 48 52 53 57 58 62 63 67 68 72 73 + 77 78 82 83 87 88 92 93 97 98 102 103 107 108 112 113 117 118 122 123 + 127 128 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 19 + 20 28 29 33 34 38 39 43 44 48 49 53 54 58 59 63 64 68 69 73 + 74 78 79 83 84 88 89 93 94 98 99 103 104 108 109 113 114 118 119 123 + 124 128 129 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 + 19 20 29 30 34 35 39 40 44 45 49 50 54 55 59 60 64 65 69 70 + 74 75 79 80 84 85 89 90 94 95 99 100 104 105 109 110 114 115 119 120 + 124 125 129 130 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 + 18 19 20 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 + 115 120 125 130 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 + 18 19 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 18 + 19 20 1 2 3 4 5 6 7 8 9 12 13 14 15 17 18 19 20 1 + 2 3 4 5 6 7 8 10 11 12 14 15 17 18 19 20 1 2 3 4 + 5 6 7 8 11 12 14 15 17 18 19 20 7 9 11 12 13 14 15 18 + 19 20 7 9 11 12 13 14 15 18 19 20 8 10 11 12 14 15 17 18 + 19 20 1 2 3 4 5 6 15 18 20 1 2 3 4 5 6 16 18 20 + 1 2 3 4 5 6 11 17 18 20 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 17 18 19 20 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 18 19 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 17 18 19 20 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 21 22 23 24 25 1 2 11 20 21 26 2 3 20 22 27 3 4 11 18 + 20 23 28 4 5 11 20 24 29 5 6 20 25 30 1 2 11 20 21 31 + 2 3 20 22 32 3 4 11 18 20 23 33 4 5 11 20 24 34 5 6 + 18 20 25 35 1 2 11 20 21 36 2 3 20 22 37 3 4 20 23 38 + 4 5 20 24 39 5 6 18 20 25 40 1 2 18 20 21 41 2 3 18 + 20 22 42 3 4 11 20 23 43 4 5 11 20 24 44 5 6 20 25 45 + 1 2 18 20 21 46 2 3 20 22 47 3 4 11 20 23 48 4 5 20 + 24 49 5 6 20 25 50 1 2 11 20 21 51 2 3 20 22 52 3 4 + 20 23 53 4 5 20 24 54 5 6 11 18 20 25 55 1 2 11 18 20 + 21 56 2 3 20 22 57 3 4 18 20 23 58 4 5 20 24 59 5 6 + 18 20 25 60 1 2 11 20 21 61 2 3 20 22 62 3 4 11 18 20 + 23 63 4 5 20 24 64 5 6 20 25 65 1 2 11 20 21 66 2 3 + 20 22 67 3 4 11 18 20 23 68 4 5 20 24 69 5 6 20 25 70 + 1 2 20 21 71 2 3 20 22 72 3 4 11 20 23 73 4 5 20 24 + 74 5 6 11 20 25 75 1 2 20 21 76 2 3 20 22 77 3 4 20 + 23 78 4 5 20 24 79 5 6 20 25 80 1 2 20 21 81 2 3 20 + 22 82 3 4 20 23 83 4 5 20 24 84 5 6 20 25 85 1 2 20 + 21 86 2 3 20 22 87 3 4 20 23 88 4 5 20 24 89 5 6 20 + 25 90 1 2 20 21 91 2 3 20 22 92 3 4 20 23 93 4 5 20 + 24 94 5 6 20 25 95 1 2 20 21 96 2 3 20 22 97 3 4 20 + 23 98 4 5 20 24 99 5 6 20 25 100 1 2 20 21 101 2 3 20 + 22 102 3 4 20 23 103 4 5 20 24 104 5 6 20 25 105 1 2 20 + 21 106 2 3 20 22 107 3 4 20 23 108 4 5 20 24 109 5 6 20 + 25 110 1 2 20 21 111 2 3 20 22 112 3 4 20 23 113 4 5 20 + 24 114 5 6 20 25 115 1 2 20 21 116 2 3 20 22 117 3 4 20 + 23 118 4 5 20 24 119 5 6 20 25 120 1 2 20 21 121 2 3 20 + 22 122 3 4 20 23 123 4 5 20 24 124 5 6 20 25 125 1 2 20 + 21 126 2 3 20 22 127 3 4 20 23 128 4 5 20 24 129 5 6 20 + 25 130 + 1.000000408955316D+00 -6.310289677458059D-07 2.096665525641583D-07 + 6.421004172807443D-08 3.956404981408923D-09 6.194351698241007D-10 + 5.637896549615107D-08 -5.637896549615107D-08 -5.637896549615107D-08 + 0.0 0.0 1.127578798332252D-06 + -5.637896549615107D-08 -5.074106752545049D-07 6.088927761993546D-07 + -5.637896549615107D-08 -2.043932134654369D-09 0.0 + 1.878335326910019D-02 3.624941025245822D-16 6.846256028048394D-16 + 8.682574753301250D-16 8.829475677343563D-16 7.596007241310538D-16 + 5.641173783660228D-16 3.637011244744196D-16 2.010050211992837D-16 + 9.149849743076945D-17 3.147608842710462D-17 7.345189304361637D-18 + 1.130718674232424D-18 1.234088333455879D-19 1.030108373210172D-20 + 6.833493328871848D-22 3.659321266573640D-23 1.588981222142243D-24 + 5.608268555010370D-26 1.610701819995700D-27 3.764561095514044D-29 + 7.172442880553562D-31 -1.426527305739000D-04 1.000147870872752D+00 + -5.613608664134517D-06 4.753307507598947D-07 -5.725276253087941D-09 + -1.773762647871990D-08 5.637896549615107D-08 -5.637896549615107D-08 + -5.637896549615107D-08 0.0 8.516936613432724D-15 + 1.127578798332252D-06 -5.637896549615107D-08 -5.074106752545049D-07 + 6.088927761993546D-07 -5.637896549615107D-08 1.437741730114794D-07 + 0.0 -1.321256637573242D+00 -1.114484955602561D-14 + 1.733296665917816D-12 -2.074384704265318D-14 2.677037702625285D-09 + -2.624046067782083D-14 6.328248787212942D-07 -2.673591396559240D-14 + 3.107915290456731D-06 -2.314677109379638D-14 3.159706807309703D-07 + -1.742469422872858D-14 2.779751095971505D-09 -1.155559277280817D-14 + 1.449127970398756D-11 -6.786512676696180D-15 1.984121417511475D-13 + -3.535647235462748D-15 1.024009300748183D-14 -1.631147863670078D-15 + 1.059880891954518D-15 -6.681999398916840D-16 1.302165587382207D-16 + -2.461975376577509D-16 1.523580661538971D-17 -8.232749965727973D-17 + 1.550961994175702D-18 -2.496269623029467D-17 1.321670733700876D-19 + -6.841421422065817D-18 9.270355296549564D-21 -1.693073277773537D-18 + 5.325857707782005D-22 -3.781317617533563D-19 2.498061216103135D-23 + -7.624842319058412D-20 9.576834498255501D-25 -1.388670166119169D-20 + 3.002645577625813D-26 -2.284276225230092D-21 7.695759909088791D-28 + -3.396618468231539D-22 1.614779109984465D-29 3.172130163875408D-06 + -4.288838244974613D-04 1.050343558192253D+00 -4.991767182946205D-02 + -9.393625077791512D-08 -2.995422221374611D-08 5.637896549615107D-08 + -5.637896549615107D-08 -5.637896549615107D-08 0.0 + -1.143995922298080D-15 1.127578798332252D-06 -5.637896549615107D-08 + -5.074106752545049D-07 6.088927761993546D-07 -5.637896549615107D-08 + -1.144809175457340D-06 0.0 1.052057933807373D+01 + -1.889024527079730D-12 2.473666237123862D-12 -3.191809705427318D-09 + 4.265404740522172D-08 -8.364604013877397D-07 3.888504579663277D-04 + -4.564798473438714D-06 3.816828131675720D-02 -5.168877237338165D-07 + 1.131986826658249D-02 -5.076469022924357D-09 3.749688039533794D-05 + -2.963390643984098D-11 1.865166154857434D-08 -4.676906106317047D-13 + 1.635970525715180D-11 -3.327468305774385D-14 1.099596759132626D-13 + -6.362139005726408D-15 5.006533924413470D-15 -1.834683316389945D-15 + 4.881095121188686D-16 -5.997685715994827D-16 5.444201036336569D-17 + -1.954991746932328D-16 5.645564756136680D-18 -5.996761655988932D-17 + 5.045512223359075D-19 -1.687755499051556D-17 3.764540326759457D-20 + -4.318695916068944D-18 2.317379201706768D-21 -1.000719796344203D-18 + 1.172540887632911D-22 -2.099449018144940D-19 4.871730427049952D-24 + -3.988113352283189D-20 1.662654519802644D-25 -6.857663320188449D-21 + 4.662922914394380D-27 -1.068200969380841D-21 1.074941789167073D-28 + 9.677614798420109D-07 -1.245291059603915D-06 -7.536840438842773D-02 + 1.075373947620392D+00 -5.109401172376238D-06 -1.163272145277006D-07 + 5.637896549615107D-08 -5.637896549615107D-08 -5.637896549615107D-08 + 0.0 2.726002957774963D-15 1.127578798332252D-06 + -5.637896549615107D-08 -5.074106752545049D-07 6.088927761993546D-07 + -5.637896549615107D-08 3.242677848902531D-06 0.0 + -2.979957580566406D+01 -2.690164063734457D-12 1.124147229838481D-14 + -5.062177166337278D-08 2.393615836679235D-14 -5.103659350425005D-04 + 3.258340252883067D-14 -5.552677810192108D-02 3.506025222747844D-14 + -1.829450204968452D-02 3.150090797476683D-14 -6.747333100065589D-05 + 2.389203133837219D-14 -3.745336840665914D-08 1.510693087010233D-14 + -3.676196846935653D-11 7.677818342037568D-15 -2.876134660295682D-13 + 2.945648553635133D-15 -1.940820822197292D-14 8.095830795573460D-16 + -3.855263683164370D-15 1.612334891334645D-16 -1.105984048240622D-15 + 2.450439846627089D-17 -3.484403436219757D-16 2.962714454342404D-18 + -1.076261635651689D-16 2.911501014282256D-19 -3.103228286741277D-17 + 2.346465182333734D-20 -8.193536641609284D-18 1.555002212474875D-21 + -1.967818836691188D-18 8.483679018543260D-23 -4.290093147860203D-19 + 3.815631846132649D-24 -8.487715775043102D-20 1.415514258958216D-25 + -1.524028579840669D-20 4.334547236644489D-27 -2.483863638318878D-21 + 1.096037222071676D-28 2.067174023068219D-07 -3.464035103206697D-07 + 8.871005547916866D-07 -1.004851656034589D-03 1.001007388811558D+00 + -3.227999513910618D-06 5.637894062715532D-08 -5.637894062715532D-08 + -5.637894062715532D-08 0.0 0.0 + 1.127578798332252D-06 -5.637894062715532D-08 -5.074106752545049D-07 + 6.088923782954225D-07 -5.637894062715532D-08 9.148621415988600D-07 + 0.0 -8.407408714294434D+00 -4.977862197962091D-14 + 8.301786856698343D-15 -9.878084678352494D-14 1.892736794660739D-14 + -1.325998230487790D-13 2.600578511758635D-14 -1.439277841873421D-13 + 2.763043835613335D-14 -1.330588200385008D-13 2.406133628386938D-14 + -1.065598347407826D-13 1.723105233259088D-14 -7.396622377087159D-14 + 9.875153944354995D-15 -4.402636024844475D-14 4.349897043042991D-15 + -2.220723876057012D-14 1.437176048199422D-15 -9.662081112407281D-15 + 3.596410837999929D-16 -3.830770878461565D-15 7.011335073232172D-17 + -1.436664440299280D-15 1.093826418912559D-17 -5.079756111055342D-16 + 1.388715480107101D-18 -1.665747200801725D-16 1.447536603658476D-19 + -5.007023509456983D-17 1.243767186728059D-20 -1.371575222480206D-17 + 8.829125121689631D-22 -3.416913538430984D-18 5.181441636060790D-23 + -7.740067027423400D-19 2.517640901542902D-24 -1.594267587579844D-19 + 1.013315498583546D-25 -2.986853872288083D-20 3.380210430601726D-27 + -5.090734445941291D-21 9.355154149199958D-29 1.471342443437607D-07 + -1.266278104594676D-07 4.008210794381739D-07 1.813951712392736D-06 + -1.041745999827981D-03 1.001039566937834D+00 5.637089728338651D-08 + -5.637089728338651D-08 -5.637896549615107D-08 -8.085981537120368D-12 + -4.542686146409396D-14 1.127425093727652D-06 -5.637896549615107D-08 + -5.073379156783631D-07 6.087796009524027D-07 -5.637089728338651D-08 + 9.095310815609992D-07 0.0 -8.358414649963379D+00 + -5.387848167289801D-14 -1.065863976940085D-13 -1.420175283796399D-13 + -1.525375420592667D-13 -1.390970129876157D-13 -1.094549255918620D-13 + -7.446164995358884D-14 -4.389770949628398D-14 -2.282676882258729D-14 + -1.078032045684525D-14 -4.709645488269049D-15 -1.906120381095478D-15 + -7.101397174837966D-16 -2.421286031373780D-16 -7.530431274023090D-17 + -2.133795108141790D-17 -5.505686860192738D-18 -1.294189415607603D-18 + -2.771874994834836D-19 -5.410633946266530D-20 -9.630518136308248D-21 + -1.259340933756903D-05 -1.634575164644048D-04 -3.157716710120440D-04 + -5.238812882453203D-04 -1.138667576014996D-04 -2.637367288116366D-05 + 1.001156237442046D+00 -1.022412441670895D-03 -1.463538410462206D-07 + 1.089178491383791D-03 6.691245653200895D-05 2.203556895256042D-02 + -1.463538410462206D-07 -9.134795516729355D-03 1.585229113698006D-02 + -1.022412441670895D-03 4.045813511766028D-06 6.691245653200895D-05 + -3.734263610839844D+01 -4.186565638519824D-05 -1.590017291164258D-07 + -1.589597218298877D-07 -1.589597218298877D-07 -1.589597218298877D-07 + -1.589597218298877D-07 -4.075298784300685D-05 1.000055276526837D+00 + 4.170673491898924D-05 -6.308013325906359D-06 7.261772225319874D-06 + -8.087516762316227D-04 4.170673491898924D-05 5.047505255788565D-04 + -4.733889363706112D-04 5.527652683667839D-05 4.606268078077846D-08 + 7.261772225319874D-06 -4.409304857254028D-01 -1.230297129950486D-06 + -1.238937771819160D-12 -2.037324342022181D-18 0.0 + 0.0 0.0 -1.230298039445188D-06 + 1.230298039445188D-06 1.000001230298039D+00 -2.460596442688257D-05 + 1.230298039445188D-06 1.107268144551199D-05 -1.328722373727942D-05 + 1.230298039445188D-06 -2.200477799974010D-09 0.0 + 2.022196725010872D-02 -7.543263791376376D-09 -7.543263791376376D-07 + -1.508652530901600D-06 -2.539273737056646D-06 -5.087317163088301D-07 + -7.543263791376376D-08 5.393962055677548D-06 -5.393962055677548D-06 + 1.000005393962056D+00 0.0 1.024852826958522D-04 + -4.854565486311913D-05 7.551546150352806D-05 -5.393962055677548D-06 + 1.420877993041358D-08 0.0 -1.305759549140930D-01 + -4.203418058068564D-09 -4.203418058068564D-09 -4.203418058068564D-09 + -4.203418058068564D-09 -4.203418058068564D-09 -4.203418058068564D-09 + 2.522051900655242D-08 2.522051900655242D-08 1.000000025220519D+00 + 5.044103090767749D-07 2.522051545383874D-07 2.269846390845487D-07 + 2.522051900655242D-08 2.554505496021875D-10 2.522051900655242D-08 + -2.408750355243683D-03 2.477248961518796D-11 -1.238624654231746D-11 + 1.238624654231746D-11 1.000000000495450D+00 -1.238624654231746D-11 + 1.238625261384962D-11 2.452476000058823D-10 1.574671382870152D-13 + 1.238624654231746D-11 -1.477152181905694D-06 2.184934178028897D-11 + -1.092467522695317D-11 1.092467522695317D-11 4.369868911169306D-10 + 9.999999999890753D-01 1.092467522695317D-11 2.163085821571542D-10 + 1.388860272448500D-13 1.092467522695317D-11 -1.302848431805614D-06 + 1.345329678770213D-07 -6.726645551680122D-08 6.726645551680122D-08 + 6.726645551680122D-08 1.000001278062882D+00 -3.363325618011004D-07 + 1.345329678770213D-07 4.668525566131621D-10 6.726645551680122D-08 + -4.453532397747040D-03 -1.054020426494162D-09 -4.277477927416840D-09 + -1.088280576766465D-09 4.067786107952998D-09 1.694434592636185D-09 + 6.575595623559138D-10 1.000000000000000D+00 1.521864578801768D-11 + -1.398565364070237D-04 -5.132014604947166D-12 -2.082700678585070D-11 + -5.298826481758834D-12 1.980600405904198D-11 8.250184389824167D-12 + 3.201650750073171D-12 1.000000000000000D+00 7.409947221787005D-14 + -6.809601131863019D-07 -6.473783287219703D-08 -4.636610242414463D-07 + -5.365741913010424D-07 7.723452881691628D-07 2.271788730467961D-07 + 6.544928510265891D-08 0.0 1.000000000000000D+00 + 1.931242499253472D-09 -1.774775609374046D-02 -4.218190908432007D-03 + -3.070430830121040D-04 -2.048411639407277D-03 8.487612940371037D-04 + -1.524399995105341D-04 -4.570157034322619D-05 -2.428856445476413D-03 + 4.073116928339005D-03 4.175942391157150D-03 9.249553550034761D-04 + 8.221305906772614D-04 -4.950208216905594D-02 4.175942391157150D-03 + 3.748018294572830D-02 -2.475163340568542D-02 4.073116928339005D-03 + 1.000018495076802D+00 8.221305906772614D-04 -1.014492340087891D+02 + -2.471087598205393D-17 -1.873189645930362D-13 4.888664885231708D-14 + -3.043990772877252D-16 -1.286887362945006D-16 -2.790847829749812D-17 + -3.319902130982655D-10 3.139515314387609D-10 -4.006040206456845D-16 + -1.686210855062899D-16 -3.125035414666135D-17 -9.123220934270648D-08 + -3.244133949920069D-06 -4.812402866748730D-16 -1.976705171837396D-16 + -3.494794412900199D-17 -5.191453169572924D-07 -9.969023521989584D-04 + -5.606729188860132D-16 -2.226699269983418D-16 -3.903872945243604D-17 + -6.099668325987295D-08 -5.238358862698078D-04 -6.322302622700565D-16 + -2.419947719317118D-16 -4.343730537307861D-17 -6.189664336631040D-10 + -2.593829776742496D-06 -6.731455535124650D-16 -2.488745852875481D-16 + -4.778463580041231D-17 -3.720013880270656D-12 -1.776293334643242D-09 + -6.517935469780786D-16 -2.327123496209888D-16 -5.103115426856043D-17 + -6.057437537676513D-14 -2.046598134020083D-12 -5.521360973271107D-16 + -1.877159742293702D-16 -5.069799238760367D-17 -4.548197620390590D-15 + -1.881829720805535D-14 -3.943213655176626D-16 -1.259239545802135D-16 + -4.296864469034077D-17 -9.248773926893387D-16 -1.645467590918122D-15 + -2.305333573641771D-16 -7.042313979789018D-17 -2.772176047218775D-17 + -2.775064164871116D-16 -4.056637719561081D-16 -1.113570922349179D-16 + -3.375268799619757D-17 -1.308748704287211D-17 -9.240036252646867D-17 + -1.296943629262385D-16 -4.625534428392427D-17 -1.425923056676471D-17 + -4.840895863954283D-18 -3.032876906515887D-17 -4.265090145600200D-17 + -1.706723743114132D-17 -5.404603734977533D-18 -1.517272582187642D-18 + -9.324217265533531D-18 -1.336685488705270D-17 -5.681662918068494D-18 + -1.854034353170231D-18 -4.197349140592874D-19 -2.625968399791454D-18 + -3.870900037102137D-18 -1.715837288230996D-18 -5.777406282236940D-19 + -1.041151557505182D-19 -6.720563303536613D-19 -1.023229862353608D-18 + -4.706283903187430D-19 -1.637971158256200D-19 -2.326514296817294D-20 + -1.557337075156648D-19 -2.458146584996669D-19 -1.172823201387139D-19 + -4.226950445047938D-20 -4.691781359097844D-21 -3.267222217268957D-20 + -5.359393661610564D-20 -2.656896049584655D-20 -9.936381092496801D-21 + -8.545038260582033D-22 -6.206423377690597D-21 -1.060338916542145D-20 + -5.472649550870706D-21 -2.128172137901634D-21 -1.405610283842565D-22 + -1.067211220312940D-21 -1.903915315123482D-21 -1.025301274472632D-21 + -4.154147080474621D-22 -2.090081288584553D-23 -1.662368100185176D-22 + -3.103005701485727D-22 -1.747504367213780D-22 -7.394070257460893D-23 + 2.863205506020705D-11 1.000000000000000D+00 -4.014349741510159D-09 + -9.617298624142734D-11 1.790963349845853D-10 -6.729825585694016D-10 + -5.825459559183344D-11 -4.065924680274335D-12 -3.366472656196606D-09 + 3.135385950869818D-09 4.016598609268840D-09 7.656726364047017D-10 + -1.155434775634845D-10 -6.809511887695407D-08 4.016598609268840D-09 + 2.810291377386420D-08 -3.369975942746350D-08 3.135385950869818D-09 + -1.771422635313269D-13 -1.155434775634845D-10 9.999941390788081D-01 + 9.258888843571604D-24 1.602456287903206D-20 2.057477099391917D-22 + 3.790063917561350D-23 1.265028470551178D-23 2.967497825759503D-23 + 2.640151404010411D-17 1.192485938020208D-16 8.872690943367984D-23 + 2.428638932088789D-23 5.485064732149495D-23 5.627280325742889D-15 + 2.097305835946361D-12 1.503074364226984D-22 3.654340714362437D-23 + 7.372330513090450D-23 1.681930622879878D-14 2.737321480594801D-10 + 1.947877940148048D-22 4.299390383295486D-23 7.854277825614900D-23 + -4.953118332693719D-16 8.360855063838102D-11 1.958871505723208D-22 + 3.781022940498793D-23 6.825535047624489D-23 -3.696815741287290D-17 + 1.911188763671634D-13 1.445337823900475D-22 1.984496358497428D-23 + 4.766340503378597D-23 -4.550524242880046D-19 -1.640866931465110D-17 + 5.772616522788313D-23 -4.807225270830030D-24 2.362661130331001D-23 + -1.189888325165020D-20 -1.973999840420913D-19 -2.738506020014500D-23 + -2.428158042480967D-23 2.509290808861137D-24 -1.294584510672371D-21 + -3.717966827098453D-21 -7.478883533280463D-23 -2.996065950125539D-23 + -1.037705815595532D-23 -3.566438890326746D-22 -5.413638615218143D-22 + -7.477866218257090D-23 -2.431505337074001D-23 -1.238172726552106D-23 + -1.375019772551033D-22 -1.876708297674201D-22 -5.030145687504091D-23 + -1.532134485362388D-23 -7.948924568162411D-24 -5.671434067641046D-23 + -7.661519347879783D-23 -2.663720744022099D-23 -8.085988361583657D-24 + -3.645409862282249D-24 -2.248603203033078D-23 -3.072957800279242D-23 + -1.198979750198010D-23 -3.714077048638117D-24 -1.364280504177280D-24 + -8.197194872253568D-24 -1.145321036994424D-23 -4.748082791043800D-24 + -1.512755170592547D-24 -4.417921329419716D-25 -2.697872741419652D-24 + -3.879402572849811D-24 -1.677462227854547D-24 -5.512122187882033D-25 + -1.265862414857133D-25 -7.973125637443234D-25 -1.184497526155601D-24 + -5.315078538823665D-25 -1.805181470815384D-25 -3.233673662629892D-26 + -2.112101611057460D-25 -3.253289983263135D-25 -1.514428048749681D-25 + -5.326447996620163D-26 -7.390221523433456D-27 -5.021731366753499D-26 + -8.038901845796694D-26 -3.888457796247278D-26 -1.419193740413248D-26 + -1.513852580882299D-27 -1.072950979457684D-26 -1.788974446777135D-26 + -9.009346205447938D-27 -3.419209741603590D-27 -2.782304323808742D-28 + -2.061430478961550D-27 -3.589193859239163D-27 -1.886021979637610D-27 + -7.457784301440527D-28 -4.595369958630025D-29 -3.566718256788164D-28 + -6.497723631603045D-28 -3.570664487244213D-28 -1.474525909938138D-28 + 1.000000000000000D+00 1.000000000000000D+00 1.000000000000000D+00 + 1.000000000000000D+00 1.000000000000000D+00 7.811995148658752D-01 + -7.201683521270752D-01 0.0 0.0 + -5.653844921875000D+04 1.740456342697144D+00 -8.308809995651245D-02 + 8.304953575134277D-02 -5.771726608276367D+00 -5.449882812500000D+04 + 9.420697018504143D-01 2.393694594502449D-02 -2.386506274342537D-02 + 7.188270683400333D-05 0.0 0.0 + -5.246062109375000D+04 1.049086261540651D+00 1.366583108901978D-01 + -1.281171441078186D-01 0.0 0.0 + -5.045838671875000D+04 1.151831865310669D+00 4.490368068218231D-02 + -4.476334899663925D-02 0.0 -4.844616015625000D+04 + 1.070025980472565D+00 1.036765098571777D+00 -1.198760032653809D+00 + -1.727943420410156D-01 0.0 -5.611478125000000D+04 + 2.215560913085937D+00 -1.629607677459717D-01 1.629607677459717D-01 + -2.116955566406250D+01 -5.408718359375000D+04 8.621966838836670D-01 + 1.399642601609230D-02 -1.399642601609230D-02 0.0 + -2.007014927585260D-07 1.844083786010742D+00 -5.207436718750000D+04 + 1.039153832942247D+00 2.189477086067200D-01 -2.052634358406067D-01 + 1.824564114212990D-02 0.0 -5.007060937500000D+04 + 1.231180489063263D+00 7.386076450347900D-02 -7.407057285308838D-02 + 0.0 0.0 -4.807021875000000D+04 + 1.099351406097412D+00 1.389152526855469D+00 -1.331271171569824D+00 + 0.0 0.0 -5.567945703125000D+04 + 2.367364883422852D+00 -2.162640094757080D-01 2.162640094757080D-01 + -4.326069641113281D+01 -5.366410156250000D+04 8.088933825492859D-01 + -1.824025437235832D-02 1.824025437235832D-02 -3.646347999572754D+00 + -5.166330859375000D+04 1.006917160004377D+00 2.334227561950684D-01 + -2.275872230529785D-01 0.0 -4.967141796875000D+04 + 1.252006113529205D+00 8.269733190536499D-02 -8.349931240081787D-02 + 0.0 0.0 -4.768283984375000D+04 + 1.108648717403412D+00 1.188438415527344D+00 -1.216734886169434D+00 + 0.0 0.0 -5.523291015625000D+04 + 2.239842414855957D+00 -2.303062677383423D-01 2.303062677383423D-01 + 6.817922439950053D-06 -6.265542602539062D+01 -5.322976562500000D+04 + 7.948511838912964D-01 -5.301721021533012D-02 5.301721021533012D-02 + 0.0 -1.431075477600098D+01 -5.124100000000000D+04 + 9.721402078866959D-01 2.035216093063354D-01 -2.001296281814575D-01 + 0.0 0.0 -4.926116406250000D+04 + 1.225186288356781D+00 7.491928339004517D-02 -7.571291923522949D-02 + 0.0 -4.728442578125000D+04 1.100826203823090D+00 + 9.620693325996399D-01 -9.302363991737366D-01 0.0 + 0.0 -5.477548437500000D+04 1.955817461013794D+00 + -2.077405452728271D-01 2.077405452728271D-01 -7.184405517578125D+01 + -5.278476953125000D+04 8.174169063568115D-01 -7.419836521148682D-02 + 7.419836521148682D-02 0.0 -2.535458374023437D+01 + -5.080805859375000D+04 9.509590044617653D-01 1.569298505783081D-01 + -1.486306786537170D-01 0.0 -4.884024609375000D+04 + 1.173709630966187D+00 5.782072991132736D-02 -5.818950012326241D-02 + 0.0 -4.687537109375000D+04 1.083329916000366D+00 + 6.685049533843994D-01 -6.127962470054626D-01 1.114175319671631D-01 + 0.0 -5.430739843750000D+04 1.642910003662109D+00 + -1.625726222991943D-01 1.625726222991943D-01 -6.851022338867187D+01 + -5.232892187500000D+04 8.625847697257996D-01 -7.636785507202148D-02 + 7.636785507202148D-02 -3.171057128906250D+01 -5.036466406250000D+04 + 9.487895332276821D-01 8.871358633041382D-02 -9.425818920135498D-02 + 0.0 -4.840866406250000D+04 1.119902253150940D+00 + 3.970580548048019D-02 -3.875695168972015D-02 -1.868509128689766D-02 + 0.0 0.0 -4.645562890625000D+04 + 1.063922047615051D+00 4.062695503234863D-01 -3.618338108062744D-01 + 0.0 0.0 0.0 + -5.382864453125000D+04 1.385215580463409D+00 -1.119138002395630D-01 + 1.119064092636108D-01 -5.542092895507812D+01 -5.186281250000000D+04 + 9.132438302040100D-01 -6.388950347900391D-02 6.388950347900391D-02 + 3.410244971746579D-06 -3.133937072753906D+01 -4.991057812500000D+04 + 9.612678736448288D-01 5.389992520213127D-02 -5.187865719199181D-02 + 0.0 -4.796682031250000D+04 1.077387571334839D+00 + 2.305793017148972D-02 -2.265761792659760D-02 0.0 + 0.0 -4.602543750000000D+04 1.047769121825695D+00 + 1.912040114402771D-01 -1.852288842201233D-01 0.0 + 0.0 -5.333987500000000D+04 1.210645496845245D+00 + -6.831127405166626D-02 6.840813159942627D-02 -2.901747131347656D+01 + -5.138643750000000D+04 9.568538181483746D-01 -4.531185328960419D-02 + 4.531185328960419D-02 0.0 2.789366590150166D-06 + -2.550216674804687D+01 -4.944372265625000D+04 9.798460863530636D-01 + 2.319774404168129D-02 -2.464760094881058D-02 0.0 + -4.751471484375000D+04 1.049969587475061D+00 1.143456250429153D-02 + -1.153665781021118D-02 0.0 -4.558538281250000D+04 + 1.036741930991411D+00 9.722059965133667D-02 -8.506804704666138D-02 + 0.0 0.0 -5.284100000000000D+04 + 1.110036253929138D+00 -3.708969801664352D-02 3.684729337692261D-02 + 0.0 -5.090041796875000D+04 9.880154319107533D-01 + -2.788387611508369D-02 2.788387611508369D-02 0.0 + 2.178428985644132D-06 -1.827397155761719D+01 -4.882808593750000D+04 + 9.973230699542910D-01 0.0 -1.018907129764557D-02 + 0.0 -4.705296093750000D+04 1.035176958888769D+00 + 4.984032362699509D-03 -5.139783024787903D-03 0.0 + -4.513525781250000D+04 1.030361384153366D+00 1.168304681777954D-01 + -2.920761704444885D-02 0.0 -5.233266406250000D+04 + 1.059764284640551D+00 -1.802648976445198D-02 2.338571846485138D-02 + 0.0 -5.040475000000000D+04 1.007092889398336D+00 + -1.836121454834938D-02 1.836121454834938D-02 0.0 + 0.0 -4.950804687500000D+04 1.010153356939554D+00 + 2.381398528814316D-02 -4.465121775865555D-03 0.0 + -4.658174609375000D+04 1.028476625680923D+00 0.0 + -1.977193402126431D-03 0.0 0.0 + -4.467566796875000D+04 1.027193285524845D+00 0.0 + -1.157634705305099D-02 0.0 -5.181486718750000D+04 + 1.037754297256470D+00 -7.477629929780960D-03 0.0 + 0.0 -4.989975390625000D+04 1.017277095466852D+00 + 0.0 0.0 0.0 + -4.388837500000000D+04 1.017999485135078D+00 0.0 + -2.978397300466895D-03 0.0 -4.610101562500000D+04 + 1.025970183312893D+00 0.0 0.0 + 0.0 -4.420680468750000D+04 1.025839652866125D+00 + 0.0 0.0 0.0 + -5.128776953125000D+04 1.029255405068398D+00 -4.347227513790131D-03 + 0.0 0.0 -4.938562109375000D+04 + 1.022067971527576D+00 0.0 0.0 + 0.0 -3.449262500000000D+04 1.022117994725704D+00 + 0.0 0.0 0.0 + -4.561122656250000D+04 1.025238625705242D+00 0.0 + -1.408393494784832D-03 0.0 -4.372866796875000D+04 + 1.025346063077450D+00 0.0 0.0 + 0.0 -5.075201562500000D+04 1.026350062340498D+00 + 0.0 0.0 0.0 + -4.886151953125000D+04 1.024067506194115D+00 0.0 + 0.0 0.0 -1.051556250000000D+05 + 1.024003818631172D+00 0.0 1.899568364024162D-02 + 0.0 -4.511256640625000D+04 1.025104723870754D+00 + 0.0 3.719797125086188D-03 0.0 + -4.324184375000000D+04 1.025196127593517D+00 0.0 + 0.0 0.0 -5.020757421875000D+04 + 1.025468096137047D+00 0.0 0.0 + 0.0 -4.833664062500000D+04 1.024810910224915D+00 + 0.0 0.0 0.0 + 0.0 1.024764768779278D+00 0.0 + 0.0 0.0 -4.460540625000000D+04 + 1.025115087628365D+00 0.0 0.0 + 0.0 -4.274633984375000D+04 1.025160629302263D+00 + 0.0 0.0 0.0 + -4.965484765625000D+04 1.025229826569557D+00 0.0 + 0.0 0.0 -4.778404687500000D+04 + 1.025058060884476D+00 0.0 0.0 + 0.0 0.0 1.025037329643965D+00 + 0.0 0.0 0.0 + -4.408996093750000D+04 1.025137882679701D+00 0.0 + 0.0 0.0 -4.224254687500000D+04 + 1.025155592709780D+00 0.0 0.0 + 0.0 -4.909400000000000D+04 1.025172512978315D+00 + 0.0 0.0 0.0 + -4.720000000000000D+04 1.025131687521935D+00 0.0 + 0.0 0.0 0.0 + 1.025124348700047D+00 0.0 0.0 + 0.0 -4.356644531250000D+04 1.025150395929813D+00 + 0.0 0.0 0.0 + -4.173044140625000D+04 1.025156177580357D+00 0.0 + 0.0 0.0 -4.852547656250000D+04 + 1.025160226970911D+00 0.0 0.0 + 0.0 -4.671788281250000D+04 1.025151398032904D+00 + 0.0 0.0 0.0 + 0.0 1.025149203836918D+00 0.0 + 0.0 0.0 -4.303501953125000D+04 + 1.025155294686556D+00 0.0 0.0 + 0.0 -4.121045312500000D+04 1.025156926363707D+00 + 0.0 0.0 0.0 + -4.794926171875000D+04 1.025157883763313D+00 0.0 + 0.0 0.0 -4.640971484375000D+04 + 1.025156144052744D+00 0.0 0.0 + 0.0 0.0 1.025155574083328D+00 + 0.0 0.0 0.0 + -4.249608593750000D+04 1.025156859308481D+00 0.0 + 0.0 0.0 -4.068298437500000D+04 + 1.025157265365124D+00 0.0 0.0 + 0.0 -4.736593359375000D+04 1.025157485157251D+00 + 0.0 0.0 0.0 + -4.888311328125000D+04 1.025157172232866D+00 0.0 + 0.0 0.0 0.0 + 1.025157041847706D+00 0.0 0.0 + 0.0 -4.194966796875000D+04 1.025157287716866D+00 + 0.0 0.0 0.0 + -4.014781640625000D+04 1.025157377123833D+00 0.0 + 0.0 0.0 -4.677552734375000D+04 + 1.025157421827316D+00 0.0 0.0 + 0.0 -9.480337500000000D+04 1.025157373398542D+00 + 0.0 0.0 0.0 + 0.0 1.025157347321510D+00 0.0 + 0.0 0.0 -4.139616796875000D+04 + 1.025157388299704D+00 0.0 0.0 + 0.0 -3.960572656250000D+04 1.025157406926155D+00 + 0.0 0.0 0.0 + -4.617843750000000D+04 1.025157414376736D+00 0.0 + 0.0 0.0 0.0 + 1.025157406926155D+00 0.0 0.0 + 0.0 0.0 1.025157403200865D+00 + 0.0 0.0 0.0 + -4.083592968750000D+04 1.025157410651445D+00 0.0 + 0.0 0.0 -3.905636718750000D+04 + 1.025157410651445D+00 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/HB/can_24.psa b/liboctave/UMFPACK/UMFPACK/Demo/HB/can_24.psa new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/HB/can_24.psa @@ -0,0 +1,12 @@ +1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. CAN 24 + 8 2 6 0 0 +PSA 24 24 92 0 +(16I5) (16I5) + 1 10 16 22 28 34 39 45 52 55 60 65 69 71 73 74 + 77 78 81 83 86 89 91 92 93 + 1 6 7 13 14 18 19 20 22 2 9 10 14 15 18 3 + 7 12 21 22 23 4 8 11 16 19 20 5 8 10 15 16 + 17 6 7 13 14 18 7 12 13 20 22 24 8 10 15 16 + 17 18 19 9 10 15 10 14 15 18 19 11 19 20 21 22 + 12 13 22 24 13 24 14 18 15 16 17 19 17 18 19 20 + 19 20 20 21 22 21 22 23 22 23 23 24 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/HB/fs_183_6.rua b/liboctave/UMFPACK/UMFPACK/Demo/HB/fs_183_6.rua new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/HB/fs_183_6.rua @@ -0,0 +1,361 @@ +1UNSYMMETRIC FACSIMILE CONVERGENCE MATRIX FS 183 6 + 357 17 72 268 0 +RUA 183 183 1069 0 +(11I7) (15I5) (4D20.12) + 1 106 142 149 152 155 158 162 166 170 175 + 181 187 196 199 203 207 210 213 216 224 232 + 239 248 255 264 270 275 280 287 292 296 300 + 303 306 309 312 315 318 321 324 327 342 352 + 356 362 365 371 374 431 435 439 440 441 442 + 443 449 456 460 466 472 479 486 490 496 503 + 507 509 515 517 523 529 532 538 545 547 554 + 558 565 567 574 581 588 590 595 599 601 607 + 610 612 618 625 632 639 646 648 655 659 661 + 668 672 674 676 682 685 690 693 697 701 706 + 709 711 717 720 726 732 736 739 744 747 749 + 753 759 765 768 773 779 785 790 795 801 807 + 813 819 828 837 844 948 950 953 965 969 971 + 973 976 977 978 979 980 981 982 983 984 985 + 986 987 988 989 991 996 1001 1006 1009 1012 1017 + 1020 1024 1027 1030 1033 1036 1039 1042 1045 1048 1050 + 1053 1056 1058 1061 1063 1065 1068 1070 + 1 2 20 21 22 23 24 26 27 42 43 44 49 50 51 + 56 57 59 60 61 62 64 65 67 68 70 71 72 73 74 + 75 76 78 79 80 81 82 83 84 86 87 89 90 91 92 + 93 94 95 96 98 99 101 102 103 104 105 106 107 109 110 + 112 113 114 115 116 118 119 122 123 124 125 126 127 128 129 + 130 131 132 133 136 137 140 144 158 159 160 161 162 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 179 182 + 1 2 42 43 45 46 51 52 53 57 58 62 63 65 66 + 76 77 84 85 96 97 99 100 108 109 110 111 118 119 120 + 121 136 137 140 141 147 3 49 137 142 143 144 146 4 137 + 138 5 137 158 6 56 137 7 64 70 137 8 59 60 137 + 9 74 78 137 10 80 81 82 137 11 91 92 93 94 137 + 12 20 42 68 69 137 13 20 21 42 43 69 73 137 158 + 14 125 137 15 103 137 178 16 115 137 181 17 112 137 18 + 122 137 19 123 137 4 20 43 45 48 137 138 140 4 21 + 43 45 57 137 140 158 4 6 22 43 56 62 137 4 7 + 12 21 23 43 64 65 137 4 7 24 43 70 76 137 4 + 8 13 21 25 43 60 84 137 4 26 57 71 137 158 27 + 56 57 61 137 28 56 62 90 137 29 57 64 65 87 137 + 158 30 57 70 76 158 20 31 43 137 21 32 43 137 33 + 127 137 34 128 137 35 130 137 36 129 137 37 131 137 38 + 132 137 39 133 137 40 126 137 41 137 180 1 2 12 13 + 20 21 42 43 69 136 137 139 140 148 158 1 2 42 43 + 46 47 49 55 136 137 1 2 44 137 2 45 53 137 140 + 145 2 43 46 43 45 47 54 137 140 48 137 138 1 2 + 3 20 31 43 49 55 56 57 59 60 61 62 64 65 67 + 68 70 71 73 74 76 78 80 81 82 87 90 91 92 93 + 94 96 99 143 144 158 159 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 1 2 50 51 2 + 51 52 53 52 53 54 55 1 2 49 56 144 159 1 2 + 49 57 58 144 158 2 57 58 149 1 2 49 59 144 160 + 1 2 49 60 144 161 1 2 43 49 61 67 144 1 2 + 49 56 62 63 144 2 62 63 150 1 2 49 64 144 162 + 1 2 49 64 65 66 144 2 65 66 151 57 67 1 2 + 49 68 144 163 43 69 1 2 49 70 144 164 1 2 49 + 71 144 165 4 21 72 1 2 49 73 144 166 1 2 49 + 74 75 144 167 53 75 1 2 49 70 76 77 144 2 76 + 77 152 1 2 49 78 79 144 168 53 79 1 2 49 80 + 83 144 169 1 2 49 81 86 144 170 1 2 49 82 89 + 144 171 53 83 1 2 60 84 85 2 84 85 153 53 86 + 1 2 49 87 144 172 57 62 88 53 89 1 2 49 90 + 144 173 1 2 49 91 95 144 174 1 2 49 92 98 144 + 175 1 2 49 93 101 144 176 1 2 49 94 102 144 177 + 53 95 1 2 49 59 96 97 144 2 96 97 154 53 98 + 1 2 49 74 99 100 144 2 99 100 155 53 101 53 102 + 1 2 43 72 103 104 104 105 137 1 2 43 105 106 4 + 20 106 1 2 107 179 2 108 109 156 1 2 108 109 110 + 2 110 111 53 111 1 2 43 72 112 113 113 114 137 1 + 2 43 72 106 114 1 2 43 67 104 115 1 2 116 182 + 117 137 183 1 2 118 119 121 2 119 120 53 120 2 118 + 121 157 1 2 43 72 113 122 1 2 43 104 123 124 4 + 22 124 1 2 43 106 125 1 2 20 26 43 126 1 2 + 20 22 43 127 1 2 21 43 128 1 2 23 43 129 1 + 2 21 22 43 130 1 2 20 27 43 131 1 2 20 24 + 43 132 1 2 21 26 43 133 4 8 13 21 43 59 96 + 134 137 4 9 13 21 43 74 99 135 137 1 2 42 43 + 136 137 138 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 + 28 29 31 32 33 34 35 36 37 38 39 40 41 42 43 + 44 45 47 48 56 57 59 60 61 62 64 65 68 70 71 + 73 74 76 78 80 81 82 84 87 90 91 92 93 94 96 + 99 103 104 105 112 113 114 115 117 122 123 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 140 142 158 178 180 + 181 183 43 138 136 137 139 1 2 4 20 21 43 45 47 + 57 136 140 141 2 53 140 141 50 142 52 143 20 43 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 49 158 + 20 21 43 158 159 21 27 43 56 160 20 23 43 64 161 + 22 43 162 20 43 163 21 26 43 158 164 43 72 165 20 + 21 43 166 24 43 167 26 158 168 25 43 169 29 43 170 + 28 43 171 43 88 172 43 88 173 43 134 174 135 175 30 + 43 176 26 56 177 107 178 41 43 179 109 180 116 181 43 + 117 182 118 183 + 1.847033583457D-01 -3.719276202958D-07 -4.461673147532D-09 -8.427241381743D-09 + -2.952632177562D-09 -1.230224173345D-09 -5.684978286767D-10 -1.382403178450D-09 + -1.856794974832D-09 1.144783933290D-10 1.190860003543D-07 -4.043289140002D-08 + 6.134758538482D-08 2.882401728331D-09 -2.882401728331D-09 4.701102853922D-09 + 5.438916710635D-08 2.074214768257D-09 4.409820290234D-10 2.310863880436D-10 + 9.891607491932D-09 2.684350720208D-09 1.838141765470D-09 -2.566882438264D-09 + 9.518614355670D-09 1.651578667869D-09 1.400407236018D-10 -1.388193610099D-08 + 8.256918013496D-09 4.026496986174D-10 -9.548140743659D-11 1.319228178802D-09 + 9.872533764800D-10 -8.178430337704D-11 2.995364457734D-10 1.165688277582D-09 + 6.650224788487D-10 -4.160228413520D-11 5.159413302221D-10 -1.619011496642D-10 + 1.298098286898D-10 -9.236423317343D-11 1.182732136117D-10 4.400353753151D-10 + 2.727607746019D-10 1.082721999108D-09 1.434879053241D-09 -6.111602434929D-11 + 7.081639208067D-10 -3.788344091693D-11 7.499472911528D-10 -1.503780554317D-10 + -1.992887573946D-10 3.841609782970D-09 -7.828529540224D-09 4.552122268525D-10 + -2.273182572124D-09 8.045368924923D-10 2.793167046723D-09 -2.793167046724D-09 + 6.855383527411D-09 -9.555567765423D-09 4.847585525976D-10 2.335796050220D-09 + 7.201575068565D-10 1.991127877266D-09 -1.991127877266D-09 2.700184238015D-09 + 1.651123707030D-09 -1.651123707030D-09 8.779995658213D-10 7.625016818901D-10 + 1.273878662141D-09 3.064293184879D-09 1.230224173345D-09 1.678753515422D-09 + 1.856794974828D-09 5.684978286771D-10 6.199014965641D-10 2.448465652502D-52 + -1.103713326844D-07 1.040881988802D-12 -6.134758538482D-08 -5.438916710635D-08 + -1.459271034585D-08 -2.782378689063D-09 -9.569233592455D-10 -4.522492485678D-09 + -9.518614355670D-09 -2.970806846671D-09 -1.400407236018D-10 -8.256918013496D-09 + -1.057115582334D-09 -9.054690731029D-10 -2.579341616382D-10 -1.003787127918D-09 + -5.726582456752D-10 -1.298098286898D-10 -1.182732136117D-10 -3.789193509658D-10 + -2.348773336850D-10 -9.323439436764D-10 -1.235590295847D-09 -8.045368924923D-10 + -7.201575068565D-10 -4.250627856579D-16 1.847055555443D-01 2.206024722187D-13 + 1.904376186660D-08 -3.706348378336D-08 -1.904376186660D-08 3.861889986008D-09 + -3.861889986002D-09 -3.861889986015D-09 2.928647459573D-08 -2.928647459573D-08 + 5.757801375901D-09 -5.757801375901D-09 1.069963117214D-09 -1.069963117214D-09 + 7.679089398996D-10 -7.679089398996D-10 3.003240578905D-10 -3.003240578905D-10 + 4.122148195741D-10 -4.122148195741D-10 4.365364829098D-10 -4.365364829098D-10 + -3.513984349104D-09 3.513984349104D-09 3.746925132324D-09 -3.746925132324D-09 + 2.504967329464D-09 2.713294194836D-09 -2.713294194836D-09 -2.504967329464D-09 + 1.203714182606D-51 3.706348378336D-08 -7.008254286648D-14 -1.500950157540D-13 + -2.500000000000D-06 1.847229489334D-01 1.625711012677D-10 3.706348378340D-09 + -3.706348378335D-09 -1.625711012698D-10 -1.625711012677D-10 -2.000000000000D-05 + 1.847029460547D-01 9.902723341668D-10 -9.902723341667D-10 1.847029450890D-01 + 2.457629270846D-11 -2.457629270846D-11 1.847029460141D-01 -9.496895772062D-10 + 9.496895772072D-10 1.847029527910D-01 -4.020236988304D-09 -3.706348378335D-09 + 7.726585366653D-09 1.847029529962D-01 -6.798659578255D-09 -1.133109929709D-09 + 7.931769507959D-09 1.847029530529D-01 -1.982942376991D-09 -6.005482627459D-09 + 7.988425004450D-09 1.847029570932D-01 -1.246680818167D-09 -7.075755995003D-09 + -3.706348378335D-09 1.202878519150D-08 1.847029556781D-01 -1.246680818167D-09 + -6.064933710003D-10 -3.706348378335D-09 -5.054111425002D-09 1.061363399250D-08 + 1.847029723998D-01 -1.139575996950D-14 1.139576217480D-14 -2.733538205877D-08 + -1.139576217480D-14 2.733538205877D-08 1.847030326876D-01 -3.617187029084D-14 + -3.617175913233D-14 7.234362556953D-14 -3.617181471159D-14 -3.617181278477D-14 + -8.762304482526D-08 8.762304482526D-08 -3.617181254052D-14 1.847029472803D-01 + -2.215887192612D-09 2.215887192612D-09 1.847029666287D-01 -1.819480113001D-08 + 2.156420874667D-08 -3.369407616668D-09 1.847029922362D-01 -3.706348378335D-08 + 4.717170663335D-08 -1.010822285000D-08 1.847030259302D-01 -8.086578280003D-08 + 8.086578280003D-08 1.847029956056D-01 -5.054111425002D-08 5.054111425002D-08 + 1.847029703350D-01 -2.527055712501D-08 2.527055712501D-08 -3.125510468576D-08 + 1.847029763195D-01 -3.125510469012D-08 -4.383761260308D-17 0.0 + 3.125510464629D-08 0.0 4.382661005511D-17 0.0 + 1.847030008084D-01 0.0 -2.259574994278D-17 -5.574398606689D-08 + 5.574398604462D-08 2.246113765381D-17 0.0 0.0 + 0.0 1.847030124526D-01 0.0 0.0 + -6.738815233337D-08 6.738815233413D-08 0.0 0.0 + 0.0 0.0 1.847029956056D-01 0.0 + 0.0 -5.054111425002D-08 5.054111424976D-08 0.0 + 0.0 1.847029956056D-01 0.0 0.0 + -5.054111425002D-08 5.054111425034D-08 0.0 0.0 + 0.0 0.0 1.847029501186D-01 0.0 + 0.0 -5.054111425056D-09 5.054111424340D-09 0.0 + 1.847029467491D-01 0.0 -1.684703808334D-09 1.684703808322D-09 + 0.0 1.847029565204D-01 0.0 0.0 + -1.145598589667D-08 1.145598589640D-08 1.847029642701D-01 0.0 + 0.0 -1.920562341501D-08 1.920562341711D-08 1.847029642701D-01 + 0.0 0.0 0.0 -1.920562341501D-08 + 1.920562341525D-08 0.0 1.847029450644D-01 0.0 + 0.0 0.0 0.0 -3.706348346422D-09 + 1.847029487708D-01 -3.706348346422D-09 3.706348346422D-09 -1.111904513493D-08 + 1.847029561835D-01 -1.111904513493D-08 1.111904513493D-08 1.847030710273D-01 + -1.259628398745D-07 1.259628398745D-07 1.847031578433D-01 -2.127788399299D-07 + 2.127788399299D-07 1.847032483111D-01 -3.032466855001D-07 3.032466855001D-07 + 1.847030479367D-01 -1.028722755757D-07 1.028722755758D-07 1.847031472617D-01 + -2.021972313040D-07 2.021972313040D-07 1.847030531121D-01 -1.080476738911D-07 + 1.080476738911D-07 1.847029753940D-01 -3.032958469560D-08 3.032958469560D-08 + 1.847031167522D-01 -1.716877491549D-07 1.716877491550D-07 1.847029888667D-01 + 4.380229901688D-08 -4.380229901668D-08 2.162322755874D-02 -2.159089062210D-02 + 7.403155341658D-07 1.269397070520D-06 -1.375006599097D-06 -6.346985352602D-07 + 2.063755196007D-01 -6.349214311879D-07 -1.375004465968D-06 1.715103318883D-53 + 2.226157903684D-10 0.0 -3.233695633350D-05 -1.500000000000D-05 + -6.346987395270D-07 1.136828992780D+01 -1.025418486412D+01 1.456594534583D-11 + 1.266709834095D+01 -1.114105063695D+00 -9.632867826155D-08 3.987593050105D-08 + -3.987593050105D-08 4.632458716482D-51 -1.136828975598D+01 0.0 + -2.223809030011D-08 1.847029673025D-01 2.223809027155D-08 0.0 + 1.847579453340D-01 -3.000000000000D-05 2.695526101250D-10 -2.695526093335D-10 + -2.500000000000D-05 -6.072063216193D-02 -6.072063216165D-02 2.454235772261D-01 + -2.651534895039D-09 0.0 1.847329477160D-01 -3.000000000000D-05 + 2.651534895039D-09 2.244826079078D-17 1.847029450831D-01 1.867160023467D-11 + -1.867160023409D-11 2.806985167356D+00 -2.806985167362D+00 5.553294944544D-03 + -2.025786930574D-08 -2.025780774980D-08 2.418462261829D-08 2.997241497978D+00 + -2.420314707957D-08 8.077212345811D-10 5.438916911567D-10 1.615750248838D-10 + 6.465663647432D-11 1.863605937612D-11 3.690836612132D-10 2.369817612475D-10 + 6.858762712566D-11 -1.863570149278D-11 7.676301581984D-10 1.903564507687D-10 + 1.129363521820D-11 6.658804341147D-10 5.726902954421D-11 4.922613821110D-11 + 7.302162281710D-11 2.080107466611D-11 8.095061777596D-11 4.618207195721D-11 + 1.046853516843D-11 9.538217415503D-12 3.055804827568D-11 1.894169175196D-11 + 7.518905381967D-11 9.964438584132D-11 2.642467459327D-11 2.798361444007D-11 + -5.553294889907D-03 -2.812538488194D+00 -5.438910648609D-10 -1.176812053461D-09 + -1.879989837104D-10 -6.465663647432D-11 -3.055693883732D-10 -7.676454577113D-10 + -2.395814258589D-10 -1.129363521820D-11 -6.658806130563D-10 -8.525210715926D-11 + -7.302108599209D-11 -2.080161149113D-11 -8.095034936346D-11 -4.618269825307D-11 + -1.046853516843D-11 -9.538217415503D-12 -3.055751145067D-11 -1.894204963531D-11 + -7.518842752382D-11 -9.964474372466D-11 1.403492583625D+00 -1.403492583686D+00 + 1.588195528744D+00 -1.403492583680D+00 1.089185606479D+00 1.273888551548D+00 + -1.089185606482D+00 -1.089185606482D+00 1.847029450644D-01 1.847029450644D-01 + 1.847029450644D-01 1.847029450644D-01 4.350827009395D-01 -4.350827009433D-01 + 7.668448156647D-10 6.197856467720D-01 -7.668448156647D-10 -4.350827017076D-01 + 3.649080717567D+00 -2.124220868494D+00 7.975186647603D-10 5.358643512506D+00 + -1.524859849077D+00 -7.975186075522D-10 -3.649080718365D+00 -2.849177309245D-04 + -2.849177309245D-04 1.849928627954D-01 -5.000000000000D-06 5.192922559506D-01 + -5.192922559754D-01 7.668446736793D-10 7.039952017928D-01 -7.668448157585D-10 + -5.192922567283D-01 5.192922559568D-01 -5.192922559568D-01 7.668444858664D-10 + 7.039952017928D-01 -7.668448457748D-10 -5.192922567284D-01 4.350827008612D-01 + -4.350827008612D-01 -4.350827017073D-01 7.668467484525D-10 6.197856467720D-01 + -4.350827017076D-01 -7.668449040245D-10 9.403400310568D-01 -5.155576445380D-01 + 7.668448049200D-10 -9.403400318322D-01 1.549825363425D+00 -4.247823865286D-01 + -7.668448167006D-10 -2.849177309250D-04 -2.849177309245D-04 1.849928627954D-01 + -5.000000000000D-06 5.192922559592D-01 -5.192922559592D-01 7.668449471519D-10 + 7.039952017928D-01 -7.668448155349D-10 -5.192922567284D-01 9.403400310659D-01 + -5.155576445636D-01 7.668452184158D-10 -9.403400318323D-01 1.549825363425D+00 + -4.247823865286D-01 -7.668448258865D-10 -2.849177309199D-04 -2.849177309245D-04 + 1.849928627954D-01 -5.000000000000D-06 0.0 1.847029450644D-01 + 4.350827009381D-01 -4.350827009381D-01 7.668448205427D-10 6.197856467720D-01 + -7.668448149473D-10 -4.350827017076D-01 -4.472000000002D+03 2.236184702945D+03 + 4.350827009255D-01 -4.350827009448D-01 7.668446561058D-10 6.197856468258D-01 + -7.668448218254D-10 -4.350827017613D-01 4.350827007568D-01 -4.350827007568D-01 + 7.668427698781D-10 6.197856467720D-01 -7.668446900881D-10 -4.350827017076D-01 + 0.0 0.0 1.847029450644D-01 4.350827009364D-01 + -4.350827009364D-01 7.668448049201D-10 6.197856467720D-01 -7.668448177886D-10 + -4.350827017076D-01 4.743804932312D-01 -4.350827009500D-01 7.668441251095D-10 + 6.590834391150D-01 -3.929779234304D-02 -7.668448253707D-10 -4.350827017076D-01 + -2.999999999975D-05 1.847329450644D-01 9.403400309955D-01 -5.155576444381D-01 + 7.668444001463D-10 -9.403400318322D-01 1.549825363425D+00 -4.247823865285D-01 + -7.668447696707D-10 -2.849177309241D-04 -2.849177309245D-04 1.849928627954D-01 + -5.000000000000D-06 4.743804932838D-01 -4.350827009530D-01 7.668440849248D-10 + 6.590834391152D-01 -3.929779234303D-02 -7.668448602203D-10 -4.350827017077D-01 + -2.999999999999D-05 1.847329450644D-01 5.052573299108D-01 -4.350827009926D-01 + 7.668427470318D-10 6.899602759560D-01 -7.017462918400D-02 -7.668448254578D-10 + -4.350827017076D-01 5.052573301008D-01 -4.350827009046D-01 7.668446147586D-10 + 6.899602759560D-01 -7.017462918399D-02 -7.668447743280D-10 -4.350827017076D-01 + 5.052573300679D-01 -4.350827009326D-01 7.668438364657D-10 6.899602759560D-01 + -7.017462918399D-02 -7.668448631294D-10 -4.350827017076D-01 -3.000000000044D-05 + 1.847329450644D-01 9.403400308871D-01 -5.155576445108D-01 -9.403400310654D-01 + 1.549825362658D+00 -4.247823865286D-01 -2.849177309421D-04 -2.849177309245D-04 + 1.849928627954D-01 -5.000000000000D-06 -2.999999999987D-05 1.847329450644D-01 + 4.350827006437D-01 -4.350827010779D-01 7.668440769557D-10 6.197856467720D-01 + -7.668449051812D-10 -4.350827017076D-01 0.0 0.0 + 1.847029450644D-01 -2.999999999970D-05 1.847329450644D-01 4.350827005205D-01 + -4.350827005205D-01 7.668488614599D-10 6.197856467720D-01 -7.668447518146D-10 + -4.350827017076D-01 5.052573300039D-01 -4.350827010178D-01 7.668460149417D-10 + 6.899602759560D-01 -7.017462918399D-02 -7.668448844073D-10 -4.350827017075D-01 + 5.052573301274D-01 -4.350827008233D-01 7.668442740500D-10 6.899602759559D-01 + -7.017462918395D-02 -7.668449594799D-10 -4.350827017075D-01 5.052573300968D-01 + -4.350827009617D-01 7.668445556523D-10 6.899602759560D-01 -7.017462918398D-02 + -7.668447849049D-10 -4.350827017076D-01 5.052573300844D-01 -4.350827009337D-01 + 7.668448795622D-10 6.899602759560D-01 -7.017462918399D-02 -7.668448363304D-10 + -4.350827017076D-01 -2.999999999962D-05 1.847329450644D-01 9.403400309788D-01 + -5.155576446611D-01 7.668446717407D-10 -9.403400318323D-01 1.549825363425D+00 + -4.247823865285D-01 -7.668448516647D-10 -2.849177308965D-04 -2.849177309245D-04 + 1.849928627954D-01 -5.000000000000D-06 -3.000000000037D-05 1.847329450644D-01 + 9.403400310374D-01 -5.155576445930D-01 7.668453760661D-10 -9.403400318323D-01 + 1.549825363425D+00 -4.247823865285D-01 -7.668448690614D-10 -2.849177309083D-04 + -2.849177309245D-04 1.849928627954D-01 -5.000000000000D-06 -2.999999999990D-05 + 1.847329450644D-01 -3.000000000006D-05 1.847329450644D-01 4.350827009285D-01 + -4.350827009431D-01 -4.350827009407D-01 -4.350827009407D-01 6.197856460051D-01 + -4.350827009413D-01 1.847030124526D-01 -6.738815233336D-08 6.738815233336D-08 + 4.350827008982D-01 -4.350827008982D-01 -4.350827009408D-01 6.197856460051D-01 + -8.701654018812D-01 0.0 0.0 1.847029450644D-01 + 4.350827009215D-01 -4.350827009215D-01 6.197856460051D-01 -4.350827009407D-01 + -2.849177309244D-04 1.849928627954D-01 -2.849177309245D-04 -5.000000000000D-06 + 4.350827009261D-01 -1.030031442269D-02 -4.247823865285D-01 1.044568032534D+00 + -4.350827009407D-01 4.247823865384D-01 6.094853315930D-01 -4.247823865286D-01 + -2.999999999995D-05 1.847329450644D-01 4.350827009375D-01 -4.350827009458D-01 + -4.350827009408D-01 -4.350827009408D-01 6.197856460052D-01 -4.350827009406D-01 + 1.847030124526D-01 -6.738815233337D-08 6.738815233335D-08 4.350827008530D-01 + -4.350827009655D-01 -4.350827009404D-01 -4.350827009409D-01 -4.350827009404D-01 + 6.197856460052D-01 4.350827009246D-01 -4.350827009487D-01 -4.350827009408D-01 + -4.350827009407D-01 -4.350827009411D-01 6.197856460052D-01 4.350827009394D-01 + -4.350827009394D-01 6.197856460051D-01 -4.350827009407D-01 1.847030124526D-01 + 6.738815233404D-08 -6.738815233336D-08 4.350827009232D-01 -1.030031443112D-02 + 1.044568032534D+00 -4.350827009407D-01 -4.247823865285D-01 4.247823865426D-01 + 6.094853315930D-01 -4.247823865285D-01 -2.999999999994D-05 1.847329450644D-01 + -2.852765693834D-04 -2.852765693766D-04 1.849932216338D-01 -5.000000000000D-06 + 4.350827009321D-01 -4.350827009321D-01 -4.350827009407D-01 -4.350827009406D-01 + -4.350827009399D-01 6.197856460052D-01 4.350827009333D-01 -4.350827009672D-01 + -4.350827009407D-01 -4.350827009418D-01 6.197856460052D-01 -4.350827009407D-01 + 0.0 0.0 1.847029450644D-01 4.350827009443D-01 + -4.350827009443D-01 -4.350827009405D-01 -4.350827009405D-01 6.197856460052D-01 + 4.350827009142D-01 -4.350827009867D-01 -4.350827009414D-01 -4.350827009414D-01 + -4.350827009405D-01 6.197856460052D-01 4.350827009181D-01 -4.350827009613D-01 + -4.350827009424D-01 -4.350827009397D-01 -4.350827009407D-01 6.197856460052D-01 + 4.350827009249D-01 -4.350827009249D-01 -8.701654018813D-01 -4.350827009407D-01 + 6.197856460052D-01 4.350827009103D+00 -4.350827009103D+00 -4.350827009408D+00 + -8.701654018815D+00 4.535529954472D+00 4.350827009378D-01 -4.350827009378D-01 + -4.350827009399D-01 -4.350827009399D-01 -4.350827009408D-01 6.197856460052D-01 + 4.350827009142D-01 -4.350827009142D-01 -4.350827009402D-01 -4.350827009421D-01 + -4.350827009407D-01 6.197856460052D-01 4.350827009067D-01 -4.350827009067D-01 + -4.350827009371D-01 -4.350827009405D-01 -4.350827009407D-01 6.197856460051D-01 + 4.350827008840D-01 -4.350827009730D-01 -4.350827009396D-01 -4.350827009396D-01 + -4.350827009407D-01 6.197856460052D-01 0.0 0.0 + 0.0 0.0 0.0 0.0 + -5.054111424998D-08 1.847029956056D-01 5.054111424909D-08 0.0 + 0.0 0.0 0.0 0.0 + 0.0 -1.617315655999D-07 1.847031067960D-01 1.617315655999D-07 + -7.321241211920D+00 7.305730107658D+00 -8.216644762503D+04 0.0 + 8.217914180010D+04 0.0 0.0 1.684191100414D+01 + 1.194789706065D+01 1.152570637560D+00 3.203752497504D+00 5.801590314942D-01 + 7.877230884797D-01 1.334284295919D+00 9.522628221382D-01 4.836031467433D-01 + 7.443160981249D-01 1.154866622749D+00 3.916088093325D+00 3.390590023192D+00 + 3.180521162968D-01 1.839620866156D+00 1.177388037480D+00 2.807229515941D+00 + 1.076822896977D+00 6.399743827870D-01 1.221654249014D+00 4.544019124820D-01 + 1.612808099323D-01 3.488652332781D-02 1.823010530775D-02 5.786837962657D-04 + 1.072060324264D-02 4.862946661956D-02 1.657310781745D-03 6.460785183840D-03 + 9.641696141492D-05 2.800172909824D-01 4.827856220525D-01 1.228202872892D+00 + 6.513945810814D-01 4.647322366774D-01 7.254763669924D-01 1.891034737044D-01 + 2.105061559182D-01 2.698759421753D-01 4.190646638201D-02 5.718157988633D-10 + -1.501867945347D+00 -1.680876639348D+01 -1.198067969175D+01 4.520363481073D-06 + 7.772471985027D-02 -7.877230884717D-01 -7.344192034644D-01 -8.162252761229D-01 + -1.360375460205D-01 -4.862946662078D-02 -1.612808099323D-01 -6.942444591950D-01 + -3.488652332776D-02 -3.916088093312D+00 -6.400398367040D-01 -1.072060324096D-02 + -3.390590023191D+00 -1.200433342982D-01 -1.823010530772D-02 -3.635598124461D-01 + -7.714200456749D-02 -4.378329988966D-01 -2.293410946601D-01 -5.786837962657D-04 + -6.460785183864D-03 -1.657310781756D-03 -1.356510001334D-01 -6.599237844325D-02 + -4.032867571532D-01 -5.499364870271D-01 -3.692655530801D-03 -4.959949739895D-03 + -1.552180105819D+00 1.419500447260D-01 -1.419500447255D-01 -2.807229515941D+00 + 1.542530815584D-01 -1.542530815580D-01 -9.250906008783D-01 1.146811089419D-02 + -1.076822896977D+00 -6.399743827853D-01 -3.180521162486D-01 -2.698759421752D-01 + -4.827856220511D-01 -1.228202872895D+00 -4.647322366781D-01 -6.513945810810D-01 + -7.254763669918D-01 -1.891034737043D-01 -2.105061559178D-01 3.692655530801D-03 + 4.959949739895D-03 5.544942290657D-51 6.299896663454D+01 -4.503227883208D+00 + -3.619795712679D-04 -1.152570637528D+00 -5.801590381620D-01 -2.874407603369D-01 + -4.190646638189D-02 -2.522974366032D-01 -1.146811089416D-02 -7.441570462111D+06 + 7.441570646800D+06 -7.650000000000D+08 -2.162948497570D+08 8.731391781590D+08 + 2.665790957288D+01 -5.034857288321D+01 -9.125978334718D-05 1.053408827308D-04 + 1.818065996370D-05 -1.053408827308D-04 -1.236997844589D-04 2.349867010473D-09 + -1.818065996370D-05 0.0 2.984376498507D+01 -2.984147403773D+00 + -8.054210242782D-02 -6.000094255021D-05 -8.054208350577D-02 2.652589908414D-01 + -5.200000000000D+03 5.200184686907D+03 -4.278550085040D+05 4.278551931939D+05 + -9.360000000000D+03 -9.360000000000D+03 9.360184686907D+03 1.846869073356D-01 + 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 + 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 + 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 1.846869073356D-01 + -2.652000000000D+06 2.652000184687D+06 -3.300000000007D+01 -1.924000000000D+02 + -1.924000000000D+02 -3.299999999994D+01 2.255846869073D+02 -1.200000000002D+03 + -1.091999999999D+03 -1.092000000006D+03 -1.200000000000D+03 2.292184686907D+03 + -3.200000000005D+03 -1.923999999994D+02 -1.923999999821D+02 -3.200000000001D+03 + 3.392584686907D+03 -1.924000000000D+02 -1.924000000000D+02 1.925846869073D+02 + -4.472000000000D+03 -2.236000000000D+03 2.236184686907D+03 -1.099999999998D+03 + -1.924000000000D+02 -1.924000000000D+02 -1.100000000000D+03 1.292584686907D+03 + -1.923999999998D+02 -1.924000000005D+02 1.925846869073D+02 -2.236000000000D+03 + -2.236000000000D+03 -2.236000000000D+03 2.236184686907D+03 -1.923999999999D+02 + -1.923999999999D+02 1.925846869073D+02 -3.329999999981D+01 -3.330000000000D+01 + 3.348468690734D+01 -1.924000000000D+02 -1.924000000002D+02 1.925846869073D+02 + -1.924000000000D+02 -1.924000000000D+02 1.925846869073D+02 -1.924000000000D+02 + -1.923999999999D+02 1.925846869073D+02 -1.923999999995D+02 -1.924000000000D+02 + 1.925846869073D+02 -1.924000000006D+02 -1.924000000000D+02 1.925846869073D+02 + -1.924000000001D+02 -1.924000000000D+02 1.925846869073D+02 -1.924000000000D+02 + 1.925846869073D+02 -1.924000000000D+02 -1.924000000000D+02 1.925846869073D+02 + -3.200000000000D+03 -3.200000000000D+03 3.200184686907D+03 -2.236000000000D+03 + 2.236184686907D+03 -2.235999999999D+03 -2.236000000000D+03 2.236184686907D+03 + -2.235999999997D+03 2.236184686907D+03 -2.236000000000D+03 2.236184686907D+03 + -2.236000000000D+03 -2.236000000000D+03 2.236184686907D+03 -2.235999999997D+03 + 2.236184686907D+03 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/HB/qc324.cua b/liboctave/UMFPACK/UMFPACK/Demo/HB/qc324.cua new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/HB/qc324.cua @@ -0,0 +1,19516 @@ +MODEL H2+ IN AN ELECTROMAGNETIC FIELD, S.I. CHU QC324 + 19512 21 1671 17820 0 +CUA 324 324 26730 0 +(16I5) (16I5) (3D22.16) (3D22.16) + 1 83 165 247 329 411 493 575 657 739 821 903 985 1067 1149 1231 + 1313 1395 1477 1559 1641 1723 1805 1887 1969 2051 2133 2215 2297 2379 2461 2543 + 2625 2707 2789 2871 2953 3035 3117 3199 3281 3363 3445 3527 3609 3691 3773 3855 + 3937 4019 4101 4183 4265 4347 4429 4511 4593 4675 4757 4839 4921 5003 5085 5167 + 5249 5331 5413 5495 5577 5659 5741 5823 5905 5987 6069 6151 6233 6315 6397 6479 + 6561 6643 6726 6809 6892 6975 7058 7141 7224 7307 7390 7473 7556 7639 7722 7805 + 7888 7971 8054 8137 8220 8303 8386 8469 8552 8635 8718 8801 8884 8967 9050 9133 + 9216 9299 9382 9465 9548 9631 9714 9797 9880 9963100461012910212102951037810461 +10544106271071010793108761095911042111251120811291113741145711540116231170611789 +11872119551203812121122041228712370124531253612619127021278512868129511303413117 +13200132831336613449135321361513698137811386413947140301411314196142791436214445 +14528146111469414777148601494315026151091519215275153581544115524156071569015773 +15856159391602216105161881627116354164371652016603166861676916852169351701817101 +17184172671735017433175161759917682177651784817931180141809718180182631834618429 +18512185951867818761188441892719010190931917619259193421942519508195911967419757 +19840199232000620089201712025320335204172049920581206632074520827209092099121073 +21155212372131921401214832156521647217292181121893219752205722139222212230322385 +22467225492263122713227952287722959230412312323205232872336923451235332361523697 +23779238612394324025241072418924271243532443524517245992468124763248452492725009 +25091251732525525337254192550125583256652574725829259112599326075261572623926321 +2640326485265672664926731 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 82 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 83 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 84 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 85 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 86 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 87 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 88 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 89 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 90 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 91 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 92 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 93 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 94 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 95 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 96 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 97 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 98 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 99 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 100 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 101 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 102 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 103 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 104 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 105 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 106 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 107 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 108 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 109 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 110 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 111 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 112 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 113 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 114 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 115 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 116 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 117 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 118 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 119 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 120 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 121 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 122 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 123 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 124 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 125 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 126 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 127 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 128 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 129 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 130 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 131 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 132 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 133 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 134 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 135 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 136 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 137 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 138 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 139 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 140 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 141 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 142 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 143 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 144 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 145 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 146 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 147 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 148 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 149 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 150 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 151 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 152 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 153 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 154 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 + 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 + 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 + 79 80 81 155 1 2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 + 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 + 77 78 79 80 81 156 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 + 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 + 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 + 75 76 77 78 79 80 81 157 1 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 + 73 74 75 76 77 78 79 80 81 158 1 2 3 4 5 6 + 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 + 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 + 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 81 159 1 2 3 4 + 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 + 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 + 69 70 71 72 73 74 75 76 77 78 79 80 81 160 1 2 + 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 + 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 161 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 + 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 + 81 162 1 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 163 2 82 83 84 85 86 87 88 89 90 91 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 + 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 + 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 + 156 157 158 159 160 161 162 164 3 82 83 84 85 86 87 88 + 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 + 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 + 153 154 155 156 157 158 159 160 161 162 165 4 82 83 84 85 + 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 + 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 + 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 + 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 160 161 162 166 5 82 + 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 + 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 + 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 + 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 + 167 6 82 83 84 85 86 87 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 + 160 161 162 168 7 82 83 84 85 86 87 88 89 90 91 92 + 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 + 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 + 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 + 157 158 159 160 161 162 169 8 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 + 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 + 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 + 154 155 156 157 158 159 160 161 162 170 9 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 + 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 + 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 + 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 161 162 171 10 82 83 + 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 + 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 + 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 172 + 11 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + 161 162 173 12 82 83 84 85 86 87 88 89 90 91 92 93 + 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 + 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 + 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 + 158 159 160 161 162 174 13 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 + 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 + 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 + 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 + 155 156 157 158 159 160 161 162 175 14 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 160 161 162 176 15 82 83 84 + 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 + 149 150 151 152 153 154 155 156 157 158 159 160 161 162 177 16 + 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 + 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 + 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 + 162 178 17 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 179 18 82 83 84 85 86 87 88 89 90 91 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 + 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 + 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 + 156 157 158 159 160 161 162 180 19 82 83 84 85 86 87 88 + 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 + 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 + 153 154 155 156 157 158 159 160 161 162 181 20 82 83 84 85 + 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 + 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 + 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 + 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 160 161 162 182 21 82 + 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 + 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 + 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 + 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 + 183 22 82 83 84 85 86 87 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 + 160 161 162 184 23 82 83 84 85 86 87 88 89 90 91 92 + 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 + 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 + 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 + 157 158 159 160 161 162 185 24 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 + 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 + 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 + 154 155 156 157 158 159 160 161 162 186 25 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 + 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 + 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 + 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 161 162 187 26 82 83 + 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 + 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 + 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 188 + 27 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + 161 162 189 28 82 83 84 85 86 87 88 89 90 91 92 93 + 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 + 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 + 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 + 158 159 160 161 162 190 29 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 + 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 + 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 + 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 + 155 156 157 158 159 160 161 162 191 30 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 160 161 162 192 31 82 83 84 + 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 + 149 150 151 152 153 154 155 156 157 158 159 160 161 162 193 32 + 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 + 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 + 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 + 162 194 33 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 195 34 82 83 84 85 86 87 88 89 90 91 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 + 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 + 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 + 156 157 158 159 160 161 162 196 35 82 83 84 85 86 87 88 + 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 + 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 + 153 154 155 156 157 158 159 160 161 162 197 36 82 83 84 85 + 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 + 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 + 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 + 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 160 161 162 198 37 82 + 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 + 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 + 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 + 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 + 199 38 82 83 84 85 86 87 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 + 160 161 162 200 39 82 83 84 85 86 87 88 89 90 91 92 + 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 + 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 + 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 + 157 158 159 160 161 162 201 40 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 + 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 + 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 + 154 155 156 157 158 159 160 161 162 202 41 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 + 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 + 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 + 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 161 162 203 42 82 83 + 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 + 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 + 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 204 + 43 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + 161 162 205 44 82 83 84 85 86 87 88 89 90 91 92 93 + 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 + 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 + 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 + 158 159 160 161 162 206 45 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 + 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 + 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 + 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 + 155 156 157 158 159 160 161 162 207 46 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 160 161 162 208 47 82 83 84 + 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 + 149 150 151 152 153 154 155 156 157 158 159 160 161 162 209 48 + 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 + 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 + 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 + 162 210 49 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 211 50 82 83 84 85 86 87 88 89 90 91 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 + 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 + 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 + 156 157 158 159 160 161 162 212 51 82 83 84 85 86 87 88 + 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 + 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 + 153 154 155 156 157 158 159 160 161 162 213 52 82 83 84 85 + 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 + 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 + 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 + 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 160 161 162 214 53 82 + 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 + 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 + 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 + 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 + 215 54 82 83 84 85 86 87 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 + 160 161 162 216 55 82 83 84 85 86 87 88 89 90 91 92 + 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 + 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 + 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 + 157 158 159 160 161 162 217 56 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 + 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 + 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 + 154 155 156 157 158 159 160 161 162 218 57 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 + 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 + 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 + 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 161 162 219 58 82 83 + 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 + 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 + 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 220 + 59 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + 161 162 221 60 82 83 84 85 86 87 88 89 90 91 92 93 + 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 + 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 + 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 + 158 159 160 161 162 222 61 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 + 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 + 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 + 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 + 155 156 157 158 159 160 161 162 223 62 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 160 161 162 224 63 82 83 84 + 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 + 149 150 151 152 153 154 155 156 157 158 159 160 161 162 225 64 + 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 + 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 + 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 + 162 226 65 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 227 66 82 83 84 85 86 87 88 89 90 91 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 + 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 + 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 + 156 157 158 159 160 161 162 228 67 82 83 84 85 86 87 88 + 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 + 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 + 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 + 153 154 155 156 157 158 159 160 161 162 229 68 82 83 84 85 + 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 + 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 + 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 + 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 160 161 162 230 69 82 + 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 + 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 + 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 + 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 + 231 70 82 83 84 85 86 87 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 + 160 161 162 232 71 82 83 84 85 86 87 88 89 90 91 92 + 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 + 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 + 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 + 157 158 159 160 161 162 233 72 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 + 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 + 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 + 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 + 154 155 156 157 158 159 160 161 162 234 73 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 + 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 + 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 + 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 161 162 235 74 82 83 + 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 + 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 + 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 236 + 75 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 + 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 + 161 162 237 76 82 83 84 85 86 87 88 89 90 91 92 93 + 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 + 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 + 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 + 158 159 160 161 162 238 77 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 + 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 + 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 + 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 + 155 156 157 158 159 160 161 162 239 78 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 160 161 162 240 79 82 83 84 + 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 + 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 + 149 150 151 152 153 154 155 156 157 158 159 160 161 162 241 80 + 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 + 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 + 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 + 162 242 81 82 83 84 85 86 87 88 89 90 91 92 93 94 + 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 + 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 + 159 160 161 162 243 82 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 244 83 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 + 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 + 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 + 234 235 236 237 238 239 240 241 242 243 245 84 163 164 165 166 + 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 + 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 + 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 + 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 241 242 243 246 85 163 + 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 + 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 + 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 + 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 + 247 86 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + 241 242 243 248 87 163 164 165 166 167 168 169 170 171 172 173 + 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 + 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 + 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 + 238 239 240 241 242 243 249 88 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 + 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 + 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 + 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 + 235 236 237 238 239 240 241 242 243 250 89 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 240 241 242 243 251 90 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 + 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 + 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 + 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 252 + 91 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 + 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 + 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 + 242 243 253 92 163 164 165 166 167 168 169 170 171 172 173 174 + 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 + 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 + 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 + 239 240 241 242 243 254 93 163 164 165 166 167 168 169 170 171 + 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 + 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 + 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 + 236 237 238 239 240 241 242 243 255 94 163 164 165 166 167 168 + 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 + 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 + 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 + 233 234 235 236 237 238 239 240 241 242 243 256 95 163 164 165 + 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 + 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 + 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 + 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 240 241 242 243 257 96 + 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 + 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 + 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 + 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 + 243 258 97 163 164 165 166 167 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 259 98 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 260 99 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 + 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 + 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 + 234 235 236 237 238 239 240 241 242 243 261 100 163 164 165 166 + 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 + 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 + 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 + 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 241 242 243 262 101 163 + 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 + 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 + 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 + 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 + 263 102 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + 241 242 243 264 103 163 164 165 166 167 168 169 170 171 172 173 + 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 + 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 + 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 + 238 239 240 241 242 243 265 104 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 + 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 + 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 + 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 + 235 236 237 238 239 240 241 242 243 266 105 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 240 241 242 243 267 106 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 + 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 + 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 + 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 268 + 107 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 + 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 + 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 + 242 243 269 108 163 164 165 166 167 168 169 170 171 172 173 174 + 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 + 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 + 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 + 239 240 241 242 243 270 109 163 164 165 166 167 168 169 170 171 + 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 + 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 + 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 + 236 237 238 239 240 241 242 243 271 110 163 164 165 166 167 168 + 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 + 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 + 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 + 233 234 235 236 237 238 239 240 241 242 243 272 111 163 164 165 + 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 + 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 + 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 + 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 240 241 242 243 273 112 + 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 + 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 + 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 + 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 + 243 274 113 163 164 165 166 167 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 275 114 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 276 115 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 + 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 + 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 + 234 235 236 237 238 239 240 241 242 243 277 116 163 164 165 166 + 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 + 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 + 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 + 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 241 242 243 278 117 163 + 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 + 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 + 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 + 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 + 279 118 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + 241 242 243 280 119 163 164 165 166 167 168 169 170 171 172 173 + 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 + 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 + 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 + 238 239 240 241 242 243 281 120 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 + 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 + 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 + 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 + 235 236 237 238 239 240 241 242 243 282 121 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 240 241 242 243 283 122 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 + 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 + 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 + 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 284 + 123 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 + 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 + 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 + 242 243 285 124 163 164 165 166 167 168 169 170 171 172 173 174 + 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 + 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 + 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 + 239 240 241 242 243 286 125 163 164 165 166 167 168 169 170 171 + 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 + 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 + 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 + 236 237 238 239 240 241 242 243 287 126 163 164 165 166 167 168 + 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 + 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 + 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 + 233 234 235 236 237 238 239 240 241 242 243 288 127 163 164 165 + 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 + 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 + 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 + 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 240 241 242 243 289 128 + 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 + 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 + 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 + 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 + 243 290 129 163 164 165 166 167 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 291 130 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 292 131 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 + 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 + 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 + 234 235 236 237 238 239 240 241 242 243 293 132 163 164 165 166 + 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 + 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 + 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 + 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 241 242 243 294 133 163 + 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 + 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 + 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 + 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 + 295 134 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + 241 242 243 296 135 163 164 165 166 167 168 169 170 171 172 173 + 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 + 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 + 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 + 238 239 240 241 242 243 297 136 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 + 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 + 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 + 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 + 235 236 237 238 239 240 241 242 243 298 137 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 240 241 242 243 299 138 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 + 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 + 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 + 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 300 + 139 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 + 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 + 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 + 242 243 301 140 163 164 165 166 167 168 169 170 171 172 173 174 + 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 + 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 + 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 + 239 240 241 242 243 302 141 163 164 165 166 167 168 169 170 171 + 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 + 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 + 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 + 236 237 238 239 240 241 242 243 303 142 163 164 165 166 167 168 + 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 + 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 + 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 + 233 234 235 236 237 238 239 240 241 242 243 304 143 163 164 165 + 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 + 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 + 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 + 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 240 241 242 243 305 144 + 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 + 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 + 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 + 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 + 243 306 145 163 164 165 166 167 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 307 146 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 308 147 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 + 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 + 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 + 234 235 236 237 238 239 240 241 242 243 309 148 163 164 165 166 + 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 + 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 + 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 + 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 241 242 243 310 149 163 + 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 + 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 + 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 + 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 + 311 150 163 164 165 166 167 168 169 170 171 172 173 174 175 176 + 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 + 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 + 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 + 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 + 241 242 243 312 151 163 164 165 166 167 168 169 170 171 172 173 + 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 + 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 + 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 + 238 239 240 241 242 243 313 152 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 + 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 + 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 + 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 + 235 236 237 238 239 240 241 242 243 314 153 163 164 165 166 167 + 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 240 241 242 243 315 154 163 164 + 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 + 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 + 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 + 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 316 + 155 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 + 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 + 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 + 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 + 242 243 317 156 163 164 165 166 167 168 169 170 171 172 173 174 + 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 + 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 + 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 + 239 240 241 242 243 318 157 163 164 165 166 167 168 169 170 171 + 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 + 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 + 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 + 236 237 238 239 240 241 242 243 319 158 163 164 165 166 167 168 + 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 + 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 + 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 + 233 234 235 236 237 238 239 240 241 242 243 320 159 163 164 165 + 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 + 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 + 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 + 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 240 241 242 243 321 160 + 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 + 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 + 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 + 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 + 243 322 161 163 164 165 166 167 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 323 162 163 164 165 166 167 168 169 170 171 172 + 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 + 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 + 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 + 237 238 239 240 241 242 243 324 163 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 164 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 165 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 166 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 167 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 168 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 169 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 170 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 171 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 172 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 173 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 174 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 175 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 176 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 177 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 178 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 179 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 180 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 181 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 182 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 183 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 184 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 185 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 186 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 187 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 188 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 189 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 190 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 191 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 192 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 193 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 194 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 195 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 196 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 197 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 198 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 199 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 200 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 201 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 202 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 203 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 204 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 205 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 206 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 207 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 208 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 209 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 210 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 211 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 212 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 213 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 214 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 215 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 216 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 217 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 218 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 219 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 220 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 221 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 222 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 223 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 224 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 225 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 226 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 227 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 228 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 229 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 230 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 231 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 232 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 233 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 234 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 235 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 236 244 245 246 247 248 + 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 + 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 + 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 + 313 314 315 316 317 318 319 320 321 322 323 324 237 244 245 246 + 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 + 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 + 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 + 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 321 322 323 324 238 244 + 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 + 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 + 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 + 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 + 239 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 + 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 + 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 + 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 + 323 324 240 244 245 246 247 248 249 250 251 252 253 254 255 256 + 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 + 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 + 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 + 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 241 244 245 246 247 248 249 250 251 252 253 254 + 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 + 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 + 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 242 244 245 246 247 248 249 250 251 252 + 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 + 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 + 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 + 317 318 319 320 321 322 323 324 243 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 + 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 + 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 + 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 + 315 316 317 318 319 320 321 322 323 324 +0.3907880596378435D+00-.5085988217165716D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-03-.1288661285438230D-020.2079634633143654D-03 +0.1760064559812521D-02-.2840382695217011D-03-.2541776982554263D-02 +0.4101905987537787D-030.3980741565709959D-02-.6424099272005126D-03 +-.7089509216132388D-020.1144101174176753D-020.1597157490519940D-01 +-.2577484145293108D-02-.6393452627818492D-010.1031771937313466D-01 +0.1315499101020305D-030.3980931060364731D-05-.6393452627818429D-01 +0.1031771937313455D-010.2927527143407817D+00-.5061033237937254D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.9826448017572174D-03-.1585786882018380D-03-.1288661285438230D-02 +0.2079634633143654D-030.1760064559812521D-02-.2840382695217011D-03 +-.2541776982554263D-020.4101905987537787D-030.3980741565709959D-02 +-.6424099272005126D-03-.7089509216132388D-020.1144101174176753D-02 +0.1597157490519940D-01-.2577484145293108D-020.1444546692054133D-03 +0.5038740027685473D-050.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2157239452786765D+00 +-.4868036798000584D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1574251928385321D-030.6107296557512106D-05 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1557709757413722D+00-.4569036816326588D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-03-.1288661285438230D-020.2079634633143654D-03 +0.1760064559812521D-02-.2840382695217011D-03-.2541776982554263D-02 +0.4101905987537787D-030.3980741565709959D-02-.6424099272005126D-03 +0.1704618139382066D-030.7186682901146465D-050.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1096566252142961D+00-.4209739735795140D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.9826448017572174D-03-.1585786882018380D-03-.1288661285438230D-02 +0.2079634633143654D-030.1760064559812521D-02-.2840382695217011D-03 +-.2541776982554263D-020.4101905987537787D-030.1835648671152865D-03 +0.8276981869115928D-05-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.7471858919825108D-01 +-.3823258786163024D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-030.1967346886630121D-030.9378276834732454D-05 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.4877067593222251D-01-.3433058868290575D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-03-.1288661285438230D-020.2079634633143654D-03 +0.2099716165654131D-030.1049065173767338D-04-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.3002068643018266D-01-.3055268727498139D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.9826448017572174D-03-.1585786882018380D-030.2232759905057449D-03 +0.1161419108758396D-040.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1700216908900937D-01 +-.2700489567358313D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.2366481518749747D-030.1274897996770195D-04 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.8517736161626044D-02-.2375203779188533D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +0.2500884437803040D-030.1389510403850428D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.3592010968872295D-02-.2082866889705388D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.2635972110537330D-03 +0.1505264954137583D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1432593898717735D-02 +-.1824749233535114D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-040.2771748002606731D-030.1622170330230075D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1397702131734624D-02-.1600580484709967D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.2908215597085934D-030.1740235273557609D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.2969361130056608D-02-.1409039418766617D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-040.3045378394557195D-03 +0.1859468584754816D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.5731212358601079D-02 +-.1248122626208860D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3183239913197660D-030.1979879124037159D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.9350157447874083D-02-.1115418954076180D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +0.3321803688867207D-030.2101475811579130D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1356118906725279D-01-.1008310886583305D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.3461073275196676D-03 +0.2224267627894746D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1815486735526482D-01 +-.9241196217609635D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-040.3601052243676528D-030.2348263614220369D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.2296699136715612D-01-.8602070427593237D-02-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.3741744183745985D-030.2473472872899837D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.2787009059662764D-01-.8140449450940520D-02 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-040.3883152702882559D-03 +0.2599904567771967D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.3276642467527989D-01 +-.7832596231436846D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.4025281426692064D-030.2727567924560386D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.3758223191522410D-01-.7656581262990280D-02-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +0.4168133998999086D-030.2856472231265750D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.4226301116560104D-01-.7592410749930865D-02 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.4311714081937841D-03 +0.2986626838560346D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.4676965794798595D-01 +-.7622058049335034D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-040.4456025356043519D-030.3118041160185087D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.5107530622773573D-01-.7729427242199239D-02-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.4601071520344119D-030.3250724673348925D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.5516275247888457D-01-.7900270743738223D-02 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-040.4746856292452647D-03 +0.3384686919130694D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.5902235975385258D-01 +-.8122077438341108D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.4893383408659858D-030.3519937502883382D-04 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.6265035698167873D-01-.8383943600343269D-02-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +0.5040656624027409D-030.3656486094640881D-040.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.6604746327913752D-01-.8676435588169473D-02 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5188679712481502D-03 +0.3794342429527186D-04-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.6921777916009794D-01 +-.8991450776860036D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-050.5337456466906940D-030.3933516308168090D-04 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.7216789658063694D-01-.9322081262977695D-02-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.5486990699241699D-030.4074017597105377D-04-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.7490618810353455D-01-.9662483409213413D-02 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-050.5637286240571986D-03 +0.4215856229213537D-040.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.7744224239182489D-01 +-.1000775519245637D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.5788346941227656D-030.4359042204118991D-04 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.7978641898553364D-01-.1035382249831074D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +0.5940176670878278D-030.4503585588621884D-040.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.8194950007742326D-01-.1069733490338830D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.6092779318629489D-03 +0.4649496517120420D-04-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.8394242094818047D-01 +-.1103557105390731D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-050.6246158793119950D-030.4796785192037780D-04 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.8577606398706922D-01-.1136635344559469D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.6400319022618756D-030.4945461884251627D-04-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.8746110392560591D-01-.1168797220454049D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-050.6555263955123291D-03 +0.5095536933526217D-040.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.8900789414501604D-01 +-.1199911733718971D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.6710997558457615D-030.5247020748947131D-04 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.9042638576277094D-01-.1229881884115071D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +0.6867523820371290D-030.5399923809358637D-040.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.9172607272565819D-01-.1258639403228736D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.7024846748638742D-03 +0.5554256663803711D-040.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.9291595739173754D-01 +-.1286140143634197D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.7182970371159094D-030.5710029931966725D-04 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.9400453211699690D-01-.1312360060645681D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +0.7341898736056463D-030.5867254304618804D-040.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.9499977321263603D-01-.1337291725485198D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.7501635911780829D-03 +0.6025940544065905D-04-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.9590914433729904D-01 +-.1360941312262982D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-050.7662185987209308D-030.6186099484599586D-04 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.9673960696151584D-01-.1383326005253246D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.7823553071748006D-030.6347742032950520D-04-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.9749763601089485D-01-.1404471777278064D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-050.7985741295434327D-03 +0.6510879168744751D-040.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.9818923917831297D-01 +-.1424411494392620D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.8148754809039821D-030.6675521944962719D-04 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.9881997870846726D-01-.1443183306359489D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +0.8312597784173505D-030.6841681488401041D-040.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.9939499471310484D-01-.1460829286515623D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.8477274413385733D-03 +0.7009369000137130D-04-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.9991902928232077D-01 +-.1477394288514098D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-050.8642788910272550D-030.7178595755996570D-04 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1003964508250222D+00-.1492924991028709D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.8809145509580565D-030.7349373107023372D-04-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1008312782070416D+00-.1507469104826736D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-050.8976348467312377D-03 +0.7521712479953038D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1012272043642645D+00 +-.1521074719639924D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.9144402060832480D-030.7695625377688507D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1015876191553175D+00-.1533789771001627D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +0.9313310588973688D-030.7871123379778959D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1019156312878210D+00-.1545661609680803D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.9483078372144148D-03 +0.8048218142901548D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1022140892071981D+00 +-.1556736658546946D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-040.9653709752434816D-030.8226921401346013D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1024856008802586D+00-.1567060143662068D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.9825209093727470D-030.8407244967502225D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1027325524394487D+00-.1576675888135830D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-040.9997580781803323D-03 +0.8589200732350710D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1029571256795995D+00 +-.1585626158817118D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1017082922445208D-020.8772800665956083D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1031613144187102D+00-.1593951557249072D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +0.1034495885158160D-020.8958056817963518D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1033469397490001D+00-.1601690947502950D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1051997411532808D-02 +0.9144981318098186D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1035156642151411D+00 +-.1608881414546571D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-040.1069587949016678D-020.9333586376667711D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1036690049640822D+00-.1615558247711579D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1087267947302331D-020.9523884285067672D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1038083459158393D+00-.1621754944615051D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-040.1105037858338542D-02 +0.9715887416290131D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1039349490076170D+00 +-.1627503231578771D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.1122898136341541D-020.9909608225435285D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1040499645650695D+00-.1632833097185782D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +0.1140849237806308D-020.1010505925022613D-030.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1041544408547741D+00-.1637772836129954D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.1158891621517917D-02 +0.1030225311152631D-03-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1042493328713475D+00 +-.1642349100959841D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-040.1177025748562945D-020.1050120251386102D-03 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1043355104113325D+00-.1646586959702118D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.1195252082340932D-020.1070192024594111D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1044137654841926D+00-.1650509957680039D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-030.1213571088575899D-02 +0.1090441918119028D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1044848191086251D+00 +-.1654140182125686D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.1231983235327929D-020.1110871227827559D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1045493275400524D+00-.1657498328427346D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +0.1250488993004788D-020.1131481258164096D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1046078879726769D+00-.1660603767060543D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.1269088834373626D-02 +0.1152273322204408D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1046610437569370D+00 +-.1663474610427858D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-030.1287783234572715D-020.1173248741709648D-03 +0.1760064559812521D-02-.2840382695217011D-03-.1288661285438230D-02 +0.2079634633143654D-030.9826448017572174D-03-.1585786882018380D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1047092891706644D+00-.1666127778982718D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1306572671123266D-020.1194408847180681D-03-.2541776982554263D-02 +0.4101905987537787D-030.1760064559812521D-02-.2840382695217011D-03 +-.1288661285438230D-020.2079634633143654D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1047530737797218D+00-.1668579066139561D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-030.1325457623941280D-02 +0.1215754977912746D-030.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1047928064214595D+00 +-.1670843201580279D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.1344438575349479D-020.1237288482050448D-03 +-.7089509216132388D-020.1144101174176753D-020.3980741565709959D-02 +-.6424099272005126D-03-.2541776982554263D-020.4101905987537787D-03 +0.1760064559812521D-02-.2840382695217011D-03-.1288661285438230D-02 +0.2079634633143654D-030.9826448017572174D-03-.1585786882018380D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1048288588419666D+00-.1672933912657333D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +0.1363516010089288D-020.1259010716643076D-030.1597157490519940D-01 +-.2577484145293108D-02-.7089509216132388D-020.1144101174176753D-02 +0.3980741565709959D-02-.6424099272005126D-03-.2541776982554263D-02 +0.4101905987537787D-030.1760064559812521D-02-.2840382695217011D-03 +-.1288661285438230D-020.2079634633143654D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1048615690158307D+00-.1674863983669926D-01 +-.6393452627818429D-010.1031771937313455D-010.1382690415332871D-02 +0.1280923047700254D-03-.6393452627818492D-010.1031771937313466D-01 +0.1597157490519940D-01-.2577484145293108D-02-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1048912441749794D+00 +-.1676645312853028D-010.1401962280695231D-020.1303026850247933D-03 +0.1315499101020305D-030.3980931060364731D-050.1495712768796483D+01 +-.8758582323213338D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1597157490519940D-01-.2577484145293108D-02 +-.6393452627818492D-010.1031771937313466D-010.1315499101020305D-03 +0.3980931060364731D-050.1444546692054133D-030.5038740027685473D-05 +-.6393452627818429D-010.1031771937313455D-010.1284018775367995D+01 +-.9274586432417488D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1597157490519940D-01-.2577484145293108D-02 +0.1444546692054133D-030.5038740027685473D-050.1574251928385321D-03 +0.6107296557512106D-050.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1103394708518522D+01 +-.9497234835585190D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1574251928385321D-030.6107296557512106D-05 +0.1704618139382066D-030.7186682901146465D-05-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.9490240426135286D+00 +-.9506540400453242D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-030.1704618139382066D-03 +0.7186682901146465D-050.1835648671152865D-030.8276981869115928D-05 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.8168613374502116D+00 +-.9363985243360058D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.1835648671152865D-030.8276981869115928D-050.1967346886630121D-03 +0.9378276834732454D-05-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.7035067815698437D+00 +-.9116507089552443D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-030.1967346886630121D-030.9378276834732454D-05 +0.2099716165654131D-030.1049065173767338D-040.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.6061012742425287D+00 +-.8799665629787737D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.2099716165654131D-03 +0.1049065173767338D-040.2232759905057449D-030.1161419108758396D-04 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.5222386826466781D+00 +-.8440152302463712D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +0.2232759905057449D-030.1161419108758396D-040.2366481518749747D-03 +0.1274897996770195D-040.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.4498924598572777D+00 +-.8057775134654636D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.2366481518749747D-030.1274897996770195D-04 +0.2500884437803040D-030.1389510403850428D-04-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.3873542691813320D+00 +-.7667024547805577D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-030.2500884437803040D-03 +0.1389510403850428D-040.2635972110537330D-030.1505264954137583D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.3331826455172370D+00 +-.7278305234447378D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.2635972110537330D-030.1505264954137583D-040.2771748002606731D-03 +0.1622170330230075D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2861600468480754D+00 +-.6898902412495479D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-040.2771748002606731D-030.1622170330230075D-04 +0.2908215597085934D-030.1740235273557609D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2452569188515565D+00 +-.6533737207443764D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.2908215597085934D-03 +0.1740235273557609D-040.3045378394557195D-030.1859468584754816D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2096016214375600D+00 +-.6185954984913972D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +0.3045378394557195D-030.1859468584754816D-040.3183239913197660D-03 +0.1979879124037159D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1784552549543353D+00 +-.5857381656377866D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3183239913197660D-030.1979879124037159D-04 +0.3321803688867207D-030.2101475811579130D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1511905818315803D+00 +-.5548875902979072D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-040.3321803688867207D-03 +0.2101475811579130D-040.3461073275196676D-030.2224267627894746D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1272743715807420D+00 +-.5260599576185822D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.3461073275196676D-030.2224267627894746D-040.3601052243676528D-03 +0.2348263614220369D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1062526075652616D+00 +-.4992223971674474D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-040.3601052243676528D-030.2348263614220369D-04 +0.3741744183745985D-030.2473472872899837D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.8773808631923941D-01 +-.4743086017203506D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.3741744183745985D-03 +0.2473472872899837D-040.3883152702882559D-030.2599904567771967D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.7140001739248367D-01 +-.4512305490328010D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +0.3883152702882559D-030.2599904567771967D-040.4025281426692064D-03 +0.2727567924560386D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.5695529621298243D-01 +-.4298872045172876D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.4025281426692064D-030.2727567924560386D-04 +0.4168133998999086D-030.2856472231265750D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.4416117636119962D-01 +-.4101708963900788D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-040.4168133998999086D-03 +0.2856472231265750D-040.4311714081937841D-030.2986626838560346D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.3280911268293057D-01 +-.3919719064856946D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.4311714081937841D-030.2986626838560346D-040.4456025356043519D-03 +0.3118041160185087D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2271958428400390D-01 +-.3751817020459010D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-040.4456025356043519D-030.3118041160185087D-04 +0.4601071520344119D-030.3250724673348925D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.1373773786865687D-01 +-.3596951403082874D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.4601071520344119D-03 +0.3250724673348925D-040.4746856292452647D-030.3384686919130694D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.5729718122685731D-02 +-.3454119037607182D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +0.4746856292452647D-030.3384686919130694D-040.4893383408659858D-03 +0.3519937502883382D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1420426245443279D-02 +-.3322373655592117D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.4893383408659858D-030.3519937502883382D-04 +0.5040656624027409D-030.3656486094640881D-04-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.7813353894945640D-02 +-.3200830386663087D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-050.5040656624027409D-03 +0.3656486094640881D-040.5188679712481502D-030.3794342429527186D-04 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1353663748560101D-01 +-.3088667262160822D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5188679712481502D-030.3794342429527186D-040.5337456466906940D-03 +0.3933516308168090D-04-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1866663060706036D-01 +-.2985124624149579D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-050.5337456466906940D-030.3933516308168090D-04 +0.5486990699241699D-030.4074017597105377D-040.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2327004940642635D-01 +-.2889503113144904D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.5486990699241699D-03 +0.4074017597105377D-040.5637286240571986D-030.4215856229213537D-04 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2740531442145211D-01 +-.2801160737399670D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +0.5637286240571986D-030.4215856229213537D-040.5788346941227656D-03 +0.4359042204118991D-040.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3112369069937826D-01 +-.2719509394869411D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.5788346941227656D-030.4359042204118991D-04 +0.5940176670878278D-030.4503585588621884D-04-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3447025807878468D-01 +-.2644011117776505D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-050.5940176670878278D-03 +0.4503585588621884D-040.6092779318629489D-030.4649496517120420D-04 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3748473833137467D-01 +-.2574174232414716D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.6092779318629489D-030.4649496517120420D-040.6246158793119950D-03 +0.4796785192037780D-04-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4020220153327811D-01 +-.2509549568248576D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-050.6246158793119950D-030.4796785192037780D-04 +0.6400319022618756D-030.4945461884251627D-040.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4265367042011983D-01 +-.2449726806321739D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.6400319022618756D-03 +0.4945461884251627D-040.6555263955123291D-030.5095536933526217D-04 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4486663845896954D-01 +-.2394331024220700D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +0.6555263955123291D-030.5095536933526217D-040.6710997558457615D-03 +0.5247020748947131D-040.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4686551484505416D-01 +-.2343019470765194D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.6710997558457615D-030.5247020748947131D-04 +0.6867523820371290D-030.5399923809358637D-04-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4867200751975501D-01 +-.2295478586186883D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-060.6867523820371290D-03 +0.5399923809358637D-040.7024846748638742D-030.5554256663803711D-04 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5030545354048027D-01 +-.2251421271226276D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.7024846748638742D-030.5554256663803711D-040.7182970371159094D-03 +0.5710029931966725D-040.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5178310465540323D-01 +-.2210584400084966D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.7182970371159094D-030.5710029931966725D-04 +0.7341898736056463D-030.5867254304618804D-04-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5312037469915137D-01 +-.2172726566553483D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-050.7341898736056463D-03 +0.5867254304618804D-040.7501635911780829D-030.6025940544065905D-04 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5433105438958483D-01 +-.2137626049149093D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.7501635911780829D-030.6025940544065905D-040.7662185987209308D-03 +0.6186099484599586D-04-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5542749823766951D-01 +-.2105078979169252D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-050.7662185987209308D-030.6186099484599586D-04 +0.7823553071748006D-030.6347742032950520D-040.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5642078755448146D-01 +-.2074897694756246D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.7823553071748006D-03 +0.6347742032950520D-040.7985741295434327D-030.6510879168744751D-04 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5732087292851082D-01 +-.2046909264043303D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +0.7985741295434327D-030.6510879168744751D-040.8148754809039821D-03 +0.6675521944962719D-040.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5813669903342966D-01 +-.2020954160960765D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.8148754809039821D-030.6675521944962719D-04 +0.8312597784173505D-030.6841681488401041D-04-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5887631419529668D-01 +-.1996885078135194D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-050.8312597784173505D-03 +0.6841681488401041D-040.8477274413385733D-030.7009369000137130D-04 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.5954696678540483D-01 +-.1974565862376031D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.8477274413385733D-030.7009369000137130D-040.8642788910272550D-03 +0.7178595755996570D-04-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6015519019946330D-01 +-.1953870559413300D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-050.8642788910272550D-030.7178595755996570D-04 +0.8809145509580565D-030.7349373107023372D-040.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6070687792621943D-01 +-.1934682555754028D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.8809145509580565D-03 +0.7349373107023372D-040.8976348467312377D-030.7521712479953038D-04 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6120734999118643D-01 +-.1916893806714917D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +0.8976348467312377D-030.7521712479953038D-040.9144402060832480D-03 +0.7695625377688507D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6166141187735572D-01 +-.1900404140831033D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.9144402060832480D-030.7695625377688507D-04 +0.9313310588973688D-030.7871123379778959D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6207340686920948D-01 +-.1885120631913809D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-040.9313310588973688D-03 +0.7871123379778959D-040.9483078372144148D-030.8048218142901548D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6244726263448086D-01 +-.1870957031024471D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.9483078372144148D-030.8048218142901548D-040.9653709752434816D-03 +0.8226921401346013D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6278653274614820D-01 +-.1857833251535415D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-040.9653709752434816D-030.8226921401346013D-04 +0.9825209093727470D-030.8407244967502225D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6309443375193149D-01 +-.1845674901271196D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.9825209093727470D-03 +0.8407244967502225D-040.9997580781803323D-030.8589200732350710D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6337387831743405D-01 +-.1834412856454672D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +0.9997580781803323D-030.8589200732350710D-040.1017082922445208D-02 +0.8772800665956083D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6362750489982794D-01 +-.1823982872836648D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1017082922445208D-020.8772800665956083D-04 +0.1034495885158160D-020.8958056817963518D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6385770434976151D-01 +-.1814325229964734D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-040.1034495885158160D-02 +0.8958056817963518D-040.1051997411532808D-020.9144981318098186D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6406664378841609D-01 +-.1805384405054882D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1051997411532808D-020.9144981318098186D-040.1069587949016678D-02 +0.9333586376667711D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6425628806305758D-01 +-.1797108773373967D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-040.1069587949016678D-020.9333586376667711D-04 +0.1087267947302331D-020.9523884285067672D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6442841904691948D-01 +-.1789450332429918D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1087267947302331D-02 +0.9523884285067672D-040.1105037858338542D-020.9715887416290131D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6458465301690153D-01 +-.1782364447603602D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +0.1105037858338542D-020.9715887416290131D-040.1122898136341541D-02 +0.9909608225435285D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6472645631459964D-01 +-.1775809617149684D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.1122898136341541D-020.9909608225435285D-04 +0.1140849237806308D-020.1010505925022613D-03-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6485515947194923D-01 +-.1769747254747372D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-040.1140849237806308D-02 +0.1010505925022613D-030.1158891621517917D-020.1030225311152631D-03 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6497196996171620D-01 +-.1764141488001286D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.1158891621517917D-020.1030225311152631D-030.1177025748562945D-02 +0.1050120251386102D-03-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6507798371474940D-01 +-.1758958971482033D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-040.1177025748562945D-020.1050120251386102D-03 +0.1195252082340932D-020.1070192024594111D-030.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6517419552992140D-01 +-.1754168713059499D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.1195252082340932D-02 +0.1070192024594111D-030.1213571088575899D-020.1090441918119028D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6526150848870371D-01 +-.1749741912422772D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +0.1213571088575899D-020.1090441918119028D-030.1231983235327929D-02 +0.1110871227827559D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6534074247406860D-01 +-.1745651810802267D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.1231983235327929D-020.1110871227827559D-03 +0.1250488993004788D-020.1131481258164096D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6541264188264254D-01 +-.1741873551014634D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-030.1250488993004788D-02 +0.1131481258164096D-030.1269088834373626D-020.1152273322204408D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6547788260955756D-01 +-.1738384047041783D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.1269088834373626D-020.1152273322204408D-030.1287783234572715D-02 +0.1173248741709648D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6553707837708347D-01 +-.1735161862434064D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-030.1287783234572715D-020.1173248741709648D-03 +0.1306572671123266D-020.1194408847180681D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6559078647072791D-01 +-.1732187096895809D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1306572671123266D-02 +0.1194408847180681D-030.1325457623941280D-020.1215754977912746D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6563951293994072D-01 +-.1729441280470915D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +0.1325457623941280D-020.1215754977912746D-030.1344438575349479D-02 +0.1237288482050448D-030.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6568371731474190D-01 +-.1726907274797979D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.1344438575349479D-020.1237288482050448D-03 +0.1363516010089288D-020.1259010716643076D-03-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6572381688442269D-01 +-.1724569180949983D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-020.1363516010089288D-02 +0.1259010716643076D-030.1382690415332871D-020.1280923047700254D-03 +0.1597157490519940D-01-.2577484145293108D-02-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6576019057985988D-01 +-.1722412253413513D-01-.6393452627818429D-010.1031771937313455D-01 +0.1382690415332871D-020.1280923047700254D-030.1401962280695231D-02 +0.1303026850247933D-03-.6393452627818492D-010.1031771937313466D-01 +0.1597157490519940D-01-.2577484145293108D-02-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.6579318249687402D-01 +-.1720422819797903D-010.1401962280695231D-020.1303026850247933D-03 +0.1315499101020305D-030.3980931060364731D-050.4820685663032476D-01 +-.5085988217165716D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1597157490519940D-01-.2577484145293108D-02 +-.6393452627818492D-010.1031771937313466D-010.1315499101020305D-03 +0.3980931060364731D-050.1444546692054133D-030.5038740027685473D-05 +-.6393452627818429D-010.1031771937313455D-01-.4982848866673706D-01 +-.5061033237937254D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1597157490519940D-01-.2577484145293108D-02 +0.1444546692054133D-030.5038740027685473D-050.1574251928385321D-03 +0.6107296557512106D-050.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1268572577288423D+00 +-.4868036798000584D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1574251928385321D-030.6107296557512106D-05 +0.1704618139382066D-030.7186682901146465D-05-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1868102272661466D+00 +-.4569036816326588D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-030.1704618139382066D-03 +0.7186682901146465D-050.1835648671152865D-030.8276981869115928D-05 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2329245777932227D+00 +-.4209739735795140D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.1835648671152865D-030.8276981869115928D-050.1967346886630121D-03 +0.9378276834732454D-05-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2678626138092677D+00 +-.3823258786163024D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-030.1967346886630121D-030.9378276834732454D-05 +0.2099716165654131D-030.1049065173767338D-040.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2938105270752963D+00 +-.3433058868290575D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.2099716165654131D-03 +0.1049065173767338D-040.2232759905057449D-030.1161419108758396D-04 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3125605165773361D+00 +-.3055268727498139D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +0.2232759905057449D-030.1161419108758396D-040.2366481518749747D-03 +0.1274897996770195D-040.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3255790339185094D+00 +-.2700489567358313D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.2366481518749747D-030.1274897996770195D-04 +0.2500884437803040D-030.1389510403850428D-04-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3340634668458927D+00 +-.2375203779188533D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-030.2500884437803040D-03 +0.1389510403850428D-040.2635972110537330D-030.1505264954137583D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3389891920386465D+00 +-.2082866889705388D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.2635972110537330D-030.1505264954137583D-040.2771748002606731D-03 +0.1622170330230075D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3411486091088010D+00 +-.1824749233535114D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-040.2771748002606731D-030.1622170330230075D-04 +0.2908215597085934D-030.1740235273557609D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3411835008757841D+00 +-.1600580484709967D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.2908215597085934D-03 +0.1740235273557609D-040.3045378394557195D-030.1859468584754816D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3396118418774621D+00 +-.1409039418766617D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +0.3045378394557195D-030.1859468584754816D-040.3183239913197660D-03 +0.1979879124037159D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3368499906489177D+00 +-.1248122626208860D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3183239913197660D-030.1979879124037159D-04 +0.3321803688867207D-030.2101475811579130D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3332310455596447D+00 +-.1115418954076180D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-040.3321803688867207D-03 +0.2101475811579130D-040.3461073275196676D-030.2224267627894746D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3290200139402660D+00 +-.1008310886583305D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.3461073275196676D-030.2224267627894746D-040.3601052243676528D-03 +0.2348263614220369D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3244263356522539D+00 +-.9241196217609635D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-040.3601052243676528D-030.2348263614220369D-04 +0.3741744183745985D-030.2473472872899837D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3196142116403626D+00 +-.8602070427593237D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.3741744183745985D-03 +0.2473472872899837D-040.3883152702882559D-030.2599904567771967D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3147111124108911D+00 +-.8140449450940520D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +0.3883152702882559D-030.2599904567771967D-040.4025281426692064D-03 +0.2727567924560386D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3098147783322389D+00 +-.7832596231436846D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.4025281426692064D-030.2727567924560386D-04 +0.4168133998999086D-030.2856472231265750D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3049989710922947D+00 +-.7656581262990280D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-040.4168133998999086D-03 +0.2856472231265750D-040.4311714081937841D-030.2986626838560346D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3003181918419177D+00 +-.7592410749930865D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.4311714081937841D-030.2986626838560346D-040.4456025356043519D-03 +0.3118041160185087D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2958115450595328D+00 +-.7622058049335034D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-040.4456025356043519D-030.3118041160185087D-04 +0.4601071520344119D-030.3250724673348925D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2915058967797831D+00 +-.7729427242199239D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.4601071520344119D-03 +0.3250724673348925D-040.4746856292452647D-030.3384686919130694D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2874184505286342D+00 +-.7900270743738223D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +0.4746856292452647D-030.3384686919130694D-040.4893383408659858D-03 +0.3519937502883382D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2835588432536662D+00 +-.8122077438341108D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.4893383408659858D-030.3519937502883382D-04 +0.5040656624027409D-030.3656486094640881D-04-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2799308460258400D+00 +-.8383943600343269D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-050.5040656624027409D-03 +0.3656486094640881D-040.5188679712481502D-030.3794342429527186D-04 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2765337397283812D+00 +-.8676435588169473D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5188679712481502D-030.3794342429527186D-040.5337456466906940D-03 +0.3933516308168090D-04-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2733634238474208D+00 +-.8991450776860036D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-050.5337456466906940D-030.3933516308168090D-04 +0.5486990699241699D-030.4074017597105377D-040.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2704133064268818D+00 +-.9322081262977695D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.5486990699241699D-03 +0.4074017597105377D-040.5637286240571986D-030.4215856229213537D-04 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2676750149039842D+00 +-.9662483409213413D-02-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +0.5637286240571986D-030.4215856229213537D-040.5788346941227656D-03 +0.4359042204118991D-040.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2651389606156939D+00 +-.1000775519245637D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.5788346941227656D-030.4359042204118991D-04 +0.5940176670878278D-030.4503585588621884D-04-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2627947840219851D+00 +-.1035382249831074D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-050.5940176670878278D-03 +0.4503585588621884D-040.6092779318629489D-030.4649496517120420D-04 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2606317029300955D+00 +-.1069733490338830D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.6092779318629489D-030.4649496517120420D-040.6246158793119950D-03 +0.4796785192037780D-04-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2586387820593383D+00 +-.1103557105390731D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-050.6246158793119950D-030.4796785192037780D-04 +0.6400319022618756D-030.4945461884251627D-040.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2568051390204495D+00 +-.1136635344559469D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.6400319022618756D-03 +0.4945461884251627D-040.6555263955123291D-030.5095536933526217D-04 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2551200990819129D+00 +-.1168797220454049D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +0.6555263955123291D-030.5095536933526217D-040.6710997558457615D-03 +0.5247020748947131D-040.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2535733088625027D+00 +-.1199911733718971D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.6710997558457615D-030.5247020748947131D-04 +0.6867523820371290D-030.5399923809358637D-04-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2521548172447478D+00 +-.1229881884115071D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-060.6867523820371290D-03 +0.5399923809358637D-040.7024846748638742D-030.5554256663803711D-04 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2508551302818606D+00 +-.1258639403228736D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.7024846748638742D-030.5554256663803711D-040.7182970371159094D-03 +0.5710029931966725D-040.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2496652456157812D+00 +-.1286140143634197D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.7182970371159094D-030.5710029931966725D-04 +0.7341898736056463D-030.5867254304618804D-04-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2485766708905219D+00 +-.1312360060645681D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-050.7341898736056463D-03 +0.5867254304618804D-040.7501635911780829D-030.6025940544065905D-04 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2475814297948827D+00 +-.1337291725485198D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.7501635911780829D-030.6025940544065905D-040.7662185987209308D-03 +0.6186099484599586D-04-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2466720586702197D+00 +-.1360941312262982D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-050.7662185987209308D-030.6186099484599586D-04 +0.7823553071748006D-030.6347742032950520D-040.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2458415960460029D+00 +-.1383326005253246D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.7823553071748006D-03 +0.6347742032950520D-040.7985741295434327D-030.6510879168744751D-04 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2450835669966239D+00 +-.1404471777278064D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +0.7985741295434327D-030.6510879168744751D-040.8148754809039821D-03 +0.6675521944962719D-040.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2443919638292058D+00 +-.1424411494392620D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.8148754809039821D-030.6675521944962719D-04 +0.8312597784173505D-030.6841681488401041D-04-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2437612242990515D+00 +-.1443183306359489D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-050.8312597784173505D-03 +0.6841681488401041D-040.8477274413385733D-030.7009369000137130D-04 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2431862082944139D+00 +-.1460829286515623D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.8477274413385733D-030.7009369000137130D-040.8642788910272550D-03 +0.7178595755996570D-04-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2426621737251980D+00 +-.1477394288514098D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-050.8642788910272550D-030.7178595755996570D-04 +0.8809145509580565D-030.7349373107023372D-040.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2421847521824966D+00 +-.1492924991028709D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.8809145509580565D-03 +0.7349373107023372D-040.8976348467312377D-030.7521712479953038D-04 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2417499248004771D+00 +-.1507469104826736D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +0.8976348467312377D-030.7521712479953038D-040.9144402060832480D-03 +0.7695625377688507D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2413539986432542D+00 +-.1521074719639924D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.9144402060832480D-030.7695625377688507D-04 +0.9313310588973688D-030.7871123379778959D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2409935838522013D+00 +-.1533789771001627D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-040.9313310588973688D-03 +0.7871123379778959D-040.9483078372144148D-030.8048218142901548D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2406655717196978D+00 +-.1545661609680803D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.9483078372144148D-030.8048218142901548D-040.9653709752434816D-03 +0.8226921401346013D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2403671138003207D+00 +-.1556736658546946D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-040.9653709752434816D-030.8226921401346013D-04 +0.9825209093727470D-030.8407244967502225D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2400956021272602D+00 +-.1567060143662068D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.9825209093727470D-03 +0.8407244967502225D-040.9997580781803323D-030.8589200732350710D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2398486505680700D+00 +-.1576675888135830D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +0.9997580781803323D-030.8589200732350710D-040.1017082922445208D-02 +0.8772800665956083D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2396240773279193D+00 +-.1585626158817118D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1017082922445208D-020.8772800665956083D-04 +0.1034495885158160D-020.8958056817963518D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2394198885888085D+00 +-.1593951557249072D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-040.1034495885158160D-02 +0.8958056817963518D-040.1051997411532808D-020.9144981318098186D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2392342632585187D+00 +-.1601690947502950D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1051997411532808D-020.9144981318098186D-040.1069587949016678D-02 +0.9333586376667711D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2390655387923777D+00 +-.1608881414546571D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-040.1069587949016678D-020.9333586376667711D-04 +0.1087267947302331D-020.9523884285067672D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2389121980434366D+00 +-.1615558247711579D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1087267947302331D-02 +0.9523884285067672D-040.1105037858338542D-020.9715887416290131D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2387728570916794D+00 +-.1621754944615051D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +0.1105037858338542D-020.9715887416290131D-040.1122898136341541D-02 +0.9909608225435285D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2386462539999018D+00 +-.1627503231578771D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.1122898136341541D-020.9909608225435285D-04 +0.1140849237806308D-020.1010505925022613D-03-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2385312384424493D+00 +-.1632833097185782D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-040.1140849237806308D-02 +0.1010505925022613D-030.1158891621517917D-020.1030225311152631D-03 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2384267621527447D+00 +-.1637772836129954D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.1158891621517917D-020.1030225311152631D-030.1177025748562945D-02 +0.1050120251386102D-03-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2383318701361712D+00 +-.1642349100959841D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-040.1177025748562945D-020.1050120251386102D-03 +0.1195252082340932D-020.1070192024594111D-030.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2382456925961863D+00 +-.1646586959702118D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.1195252082340932D-02 +0.1070192024594111D-030.1213571088575899D-020.1090441918119028D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2381674375233261D+00 +-.1650509957680039D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +0.1213571088575899D-020.1090441918119028D-030.1231983235327929D-02 +0.1110871227827559D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2380963838988937D+00 +-.1654140182125686D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.1231983235327929D-020.1110871227827559D-03 +0.1250488993004788D-020.1131481258164096D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2380318754674663D+00 +-.1657498328427346D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-030.1250488993004788D-02 +0.1131481258164096D-030.1269088834373626D-020.1152273322204408D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2379733150348419D+00 +-.1660603767060543D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.1269088834373626D-020.1152273322204408D-030.1287783234572715D-02 +0.1173248741709648D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2379201592505817D+00 +-.1663474610427858D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-030.1287783234572715D-020.1173248741709648D-03 +0.1306572671123266D-020.1194408847180681D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2378719138368543D+00 +-.1666127778982718D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1306572671123266D-02 +0.1194408847180681D-030.1325457623941280D-020.1215754977912746D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2378281292277970D+00 +-.1668579066139561D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +0.1325457623941280D-020.1215754977912746D-030.1344438575349479D-02 +0.1237288482050448D-030.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2377883965860592D+00 +-.1670843201580279D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.1344438575349479D-020.1237288482050448D-03 +0.1363516010089288D-020.1259010716643076D-03-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2377523441655522D+00 +-.1672933912657333D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-020.1363516010089288D-02 +0.1259010716643076D-030.1382690415332871D-020.1280923047700254D-03 +0.1597157490519940D-01-.2577484145293108D-02-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2377196339916881D+00 +-.1674863983669926D-01-.6393452627818429D-010.1031771937313455D-01 +0.1382690415332871D-020.1280923047700254D-030.1401962280695231D-02 +0.1303026850247933D-03-.6393452627818492D-010.1031771937313466D-01 +0.1597157490519940D-01-.2577484145293108D-02-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2376899588325394D+00 +-.1676645312853028D-010.1401962280695231D-020.1303026850247933D-03 +0.1315499101020305D-030.3980931060364731D-050.1153131565788964D+01 +-.8758582323213338D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-03-.7089509216132388D-02 +0.1144101174176753D-020.1597157490519940D-01-.2577484145293108D-02 +-.6393452627818492D-010.1031771937313466D-010.1444546692054133D-03 +0.5038740027685473D-05-.6393452627818429D-010.1031771937313455D-01 +0.9414375723604762D+00-.9274586432417488D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-03-.1288661285438230D-020.2079634633143654D-03 +0.1760064559812521D-02-.2840382695217011D-03-.2541776982554263D-02 +0.4101905987537787D-030.3980741565709959D-02-.6424099272005126D-03 +-.7089509216132388D-020.1144101174176753D-020.1597157490519940D-01 +-.2577484145293108D-020.1574251928385321D-030.6107296557512106D-05 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.7608135055110032D+00-.9497234835585190D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.9826448017572174D-03-.1585786882018380D-03-.1288661285438230D-02 +0.2079634633143654D-030.1760064559812521D-02-.2840382695217011D-03 +-.2541776982554263D-020.4101905987537787D-030.3980741565709959D-02 +-.6424099272005126D-03-.7089509216132388D-020.1144101174176753D-02 +0.1704618139382066D-030.7186682901146465D-05-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.6064428396060100D+00 +-.9506540400453242D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.1760064559812521D-02 +-.2840382695217011D-03-.2541776982554263D-020.4101905987537787D-03 +0.3980741565709959D-02-.6424099272005126D-030.1835648671152865D-03 +0.8276981869115928D-050.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.4742801344426930D+00-.9363985243360058D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-03-.1288661285438230D-020.2079634633143654D-03 +0.1760064559812521D-02-.2840382695217011D-03-.2541776982554263D-02 +0.4101905987537787D-030.1967346886630121D-030.9378276834732454D-05 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.3609255785623250D+00-.9116507089552443D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.9826448017572174D-03-.1585786882018380D-03-.1288661285438230D-02 +0.2079634633143654D-030.1760064559812521D-02-.2840382695217011D-03 +0.2099716165654131D-030.1049065173767338D-040.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.2635200712350100D+00 +-.8799665629787737D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-03-.7727812230408974D-03 +0.1247110170406368D-030.9826448017572174D-03-.1585786882018380D-03 +-.1288661285438230D-020.2079634633143654D-030.2232759905057449D-03 +0.1161419108758396D-04-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +0.1796574796391594D+00-.8440152302463712D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.6226054234809117D-03-.1004757274921672D-03 +-.7727812230408974D-030.1247110170406368D-030.9826448017572174D-03 +-.1585786882018380D-030.2366481518749747D-030.1274897996770195D-04 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-010.1073112568497590D+00-.8057775134654636D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +-.5114288231755168D-030.8253410768850847D-040.6226054234809117D-03 +-.1004757274921672D-03-.7727812230408974D-030.1247110170406368D-03 +0.2500884437803040D-030.1389510403850428D-04-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-010.4477306617381333D-01 +-.7667024547805577D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.4268045368520104D-03 +-.6887748599651892D-04-.5114288231755168D-030.8253410768850847D-04 +0.6226054234809117D-03-.1004757274921672D-030.2635972110537330D-03 +0.1505264954137583D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.9398557490281734D-02-.7278305234447378D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-04-.3608796739013979D-030.5823856716450639D-04 +0.4268045368520104D-03-.6887748599651892D-04-.5114288231755168D-03 +0.8253410768850847D-040.2771748002606731D-030.1622170330230075D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.5642115615944338D-01-.6898902412495479D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3085010747980624D-03-.4978573708714430D-04-.3608796739013979D-03 +0.5823856716450639D-040.4268045368520104D-03-.6887748599651892D-04 +0.2908215597085934D-030.1740235273557609D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.9732428415596228D-01 +-.6533737207443764D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2661733971656788D-03 +0.4295491929665637D-040.3085010747980624D-03-.4978573708714430D-04 +-.3608796739013979D-030.5823856716450639D-040.3045378394557195D-03 +0.1859468584754816D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.1329795815699588D+00-.6185954984913972D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.2314578281220329D-03-.3735253948527681D-04 +-.2661733971656788D-030.4295491929665637D-040.3085010747980624D-03 +-.4978573708714430D-040.3183239913197660D-030.1979879124037159D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.1641259480531834D+00-.5857381656377866D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +-.2026106452901076D-030.3269719667613068D-040.2314578281220329D-03 +-.3735253948527681D-04-.2661733971656788D-030.4295491929665637D-04 +0.3321803688867207D-030.2101475811579130D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.1913906211759385D+00 +-.5548875902979072D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.1783582025511267D-03 +-.2878335054540236D-04-.2026106452901076D-030.3269719667613068D-04 +0.2314578281220329D-03-.3735253948527681D-040.3461073275196676D-03 +0.2224267627894746D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.2153068314267767D+00-.5260599576185822D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-04-.1577525118211425D-030.2545801528732096D-04 +0.1783582025511267D-03-.2878335054540236D-04-.2026106452901076D-03 +0.3269719667613068D-040.3601052243676528D-030.2348263614220369D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.2363285954422571D+00-.4992223971674474D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1577525118211425D-03 +0.2545801528732096D-040.1783582025511267D-03-.2878335054540236D-04 +0.3741744183745985D-030.2473472872899837D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2548431166882794D+00 +-.4743086017203506D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-04-.1247774371157844D-03 +0.2013651551366699D-040.1400760388418106D-03-.2260539561021587D-04 +-.1577525118211425D-030.2545801528732096D-040.3883152702882559D-03 +0.2599904567771967D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.2711811856150351D+00-.4512305490328010D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.1114272391272199D-03-.1798206776156415D-04 +-.1247774371157844D-030.2013651551366699D-040.1400760388418106D-03 +-.2260539561021587D-040.4025281426692064D-030.2727567924560386D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.2856259067945363D+00-.4298872045172876D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +-.9968672138364864D-040.1608738933935444D-040.1114272391272199D-03 +-.1798206776156415D-04-.1247774371157844D-030.2013651551366699D-04 +0.4168133998999086D-030.2856472231265750D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.2984200266463191D+00 +-.4101708963900788D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.8928564729752786D-04 +-.1440886961226929D-04-.9968672138364864D-040.1608738933935444D-04 +0.1114272391272199D-03-.1798206776156415D-040.4311714081937841D-03 +0.2986626838560346D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3097720903245881D+00-.3919719064856946D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-04-.8000610566205314D-040.1291134218726644D-04 +0.8928564729752786D-04-.1440886961226929D-04-.9968672138364864D-04 +0.1608738933935444D-040.4456025356043519D-030.3118041160185087D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3198616187235148D+00-.3751817020459010D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.7167060586276605D-04-.1156616372469904D-04-.8000610566205314D-04 +0.1291134218726644D-040.8928564729752786D-04-.1440886961226929D-04 +0.4601071520344119D-030.3250724673348925D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3288434651388619D+00 +-.3596951403082874D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-05-.6413319184916952D-04 +0.1034977991584680D-040.7167060586276605D-04-.1156616372469904D-04 +-.8000610566205314D-040.1291134218726644D-040.4746856292452647D-03 +0.3384686919130694D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3368514848848330D+00-.3454119037607182D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5727272713271265D-04-.9242641819512053D-05 +-.6413319184916952D-040.1034977991584680D-040.7167060586276605D-04 +-.1156616372469904D-040.4893383408659858D-030.3519937502883382D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3440016292529620D+00-.3322373655592117D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +-.5098776122625716D-040.8228377410789080D-050.5727272713271265D-04 +-.9242641819512053D-05-.6413319184916952D-040.1034977991584680D-04 +0.5040656624027409D-030.3656486094640881D-04-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3503945569024643D+00 +-.3200830386663087D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.4519256146756725D-04 +-.7293151198878877D-05-.5098776122625716D-040.8228377410789080D-05 +0.5727272713271265D-04-.9242641819512053D-050.5188679712481502D-03 +0.3794342429527186D-040.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3561178404931197D+00-.3088667262160822D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-05-.3981401266047105D-040.6425163892851680D-05 +0.4519256146756725D-04-.7293151198878877D-05-.5098776122625716D-04 +0.8228377410789080D-050.5337456466906940D-030.3933516308168090D-04 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3612478336145791D+00-.2985124624149579D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3981401266047105D-04 +0.6425163892851680D-050.4519256146756725D-04-.7293151198878877D-05 +0.5486990699241699D-030.4074017597105377D-040.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3658512524139451D+00 +-.2889503113144904D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-05-.3006329973746788D-04 +0.4851599099553577D-050.3478916893609630D-04-.5614257322333374D-05 +-.3981401266047105D-040.6425163892851680D-050.5637286240571986D-03 +0.4215856229213537D-04-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3699865174289708D+00-.2801160737399670D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.2558831255668139D-04-.4129428081521270D-05 +-.3006329973746788D-040.4851599099553577D-050.3478916893609630D-04 +-.5614257322333374D-050.5788346941227656D-030.4359042204118991D-04 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3737048937068970D+00-.2719509394869411D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +-.2132146425429693D-040.3440846403443515D-050.2558831255668139D-04 +-.4129428081521270D-05-.3006329973746788D-040.4851599099553577D-05 +0.5940176670878278D-030.4503585588621884D-04-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3770514610863034D+00 +-.2644011117776505D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.1722429384947072D-04 +-.2779647252972395D-05-.2132146425429693D-040.3440846403443515D-05 +0.2558831255668139D-04-.4129428081521270D-050.6092779318629489D-03 +0.4649496517120420D-040.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3800659413388934D+00-.2574174232414716D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-05-.1326172498198105D-040.2140170026010777D-05 +0.1722429384947072D-04-.2779647252972395D-05-.2132146425429693D-04 +0.3440846403443515D-050.6246158793119950D-030.4796785192037780D-04 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3827834045407968D+00-.2509549568248576D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.9401297415863014D-05-.1517176307183306D-05-.1326172498198105D-04 +0.2140170026010777D-050.1722429384947072D-04-.2779647252972395D-05 +0.6400319022618756D-030.4945461884251627D-040.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3852348734276386D+00 +-.2449726806321739D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-06-.5612495043042305D-05 +0.9057414234252119D-060.9401297415863014D-05-.1517176307183306D-05 +-.1326172498198105D-040.2140170026010777D-050.6555263955123291D-03 +0.5095536933526217D-04-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3874478414664883D+00-.2394331024220700D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.1866143715512185D-05-.3011572664637594D-06 +-.5612495043042305D-050.9057414234252119D-060.9401297415863014D-05 +-.1517176307183306D-050.6710997558457615D-030.5247020748947131D-04 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3894467178525729D+00-.2343019470765194D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.1866143715712640D-05-.3011572664961087D-060.1866143715512185D-05 +-.3011572664637594D-06-.5612495043042305D-050.9057414234252119D-06 +0.6867523820371290D-030.5399923809358637D-04-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3912532105272737D+00 +-.2295478586186883D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-05-.5612495043095234D-05 +0.9057414234337534D-060.1866143715712640D-05-.3011572664961087D-06 +0.1866143715512185D-05-.3011572664637594D-060.7024846748638742D-03 +0.5554256663803711D-040.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3928866565479990D+00-.2251421271226276D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.9401297415583386D-05-.1517176307138179D-05 +-.5612495043095234D-050.9057414234337534D-060.1866143715712640D-05 +-.3011572664961087D-060.7182970371159094D-030.5710029931966725D-04 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3943643076629220D+00-.2210584400084966D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +-.1326172498190355D-040.2140170025998270D-050.9401297415583386D-05 +-.1517176307138179D-05-.5612495043095234D-050.9057414234337534D-06 +0.7341898736056463D-030.5867254304618804D-04-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3957015777066701D+00 +-.2172726566553483D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.1722429384915639D-04 +-.2779647252921669D-05-.1326172498190355D-040.2140170025998270D-05 +0.9401297415583386D-05-.1517176307138179D-050.7501635911780829D-03 +0.6025940544065905D-040.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3969122573971036D+00-.2137626049149093D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-05-.2132146425430071D-040.3440846403444125D-05 +0.1722429384915639D-04-.2779647252921669D-05-.1326172498190355D-04 +0.2140170025998270D-050.7662185987209308D-030.6186099484599586D-04 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.3980087012451882D+00-.2105078979169252D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.2558831255660659D-04-.4129428081509198D-05-.2132146425430071D-04 +0.3440846403444125D-050.1722429384915639D-04-.2779647252921669D-05 +0.7823553071748006D-030.6347742032950520D-040.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.3990019905620002D+00 +-.2074897694756246D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3006329973748652D-04 +0.4851599099556584D-050.2558831255660659D-04-.4129428081509198D-05 +-.2132146425430071D-040.3440846403444125D-050.7985741295434327D-03 +0.6510879168744751D-04-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.3999020759360296D+00-.2046909264043303D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.3478916893617300D-04-.5614257322345751D-05 +-.3006329973748652D-040.4851599099556584D-050.2558831255660659D-04 +-.4129428081509198D-050.8148754809039821D-030.6675521944962719D-04 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4007179020409484D+00-.2020954160960765D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +-.3981401266032415D-040.6425163892827973D-050.3478916893617300D-04 +-.5614257322345751D-05-.3006329973748652D-040.4851599099556584D-05 +0.8312597784173505D-030.6841681488401041D-04-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4014575172028155D+00 +-.1996885078135194D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.4519256146769957D-04 +-.7293151198900231D-05-.3981401266032415D-040.6425163892827973D-05 +0.3478916893617300D-04-.5614257322345751D-050.8477274413385733D-03 +0.7009369000137130D-040.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4021281697929236D+00-.1974565862376031D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-05-.5098776122600387D-040.8228377410748204D-05 +0.4519256146769957D-04-.7293151198900231D-05-.3981401266032415D-04 +0.6425163892827973D-050.8642788910272550D-030.7178595755996570D-04 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4027363932069820D+00-.1953870559413300D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.5727272713271211D-04-.9242641819511967D-05-.5098776122600387D-04 +0.8228377410748204D-050.4519256146769957D-04-.7293151198900231D-05 +0.8809145509580565D-030.7349373107023372D-040.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4032880809337382D+00 +-.1934682555754028D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-04-.6413319184882657D-04 +0.1034977991579146D-040.5727272713271211D-04-.9242641819511967D-05 +-.5098776122600387D-040.8228377410748204D-050.8976348467312377D-03 +0.7521712479953038D-04-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4037885529987051D+00-.1916893806714917D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.7167060586256731D-04-.1156616372466696D-04 +-.6413319184882657D-040.1034977991579146D-040.5727272713271211D-04 +-.9242641819511967D-050.9144402060832480D-030.7695625377688507D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4042426148848744D+00-.1900404140831033D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +-.8000610566205206D-040.1291134218726627D-040.7167060586256731D-04 +-.1156616372466696D-04-.6413319184882657D-040.1034977991579146D-04 +0.9313310588973688D-030.7871123379778959D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4046546098767282D+00 +-.1885120631913809D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.8928564729795884D-04 +-.1440886961233884D-04-.8000610566205206D-040.1291134218726627D-04 +0.7167060586256731D-04-.1156616372466696D-040.9483078372144148D-03 +0.8048218142901548D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4050284656419996D+00-.1870957031024471D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-04-.9968672138332729D-040.1608738933930258D-04 +0.8928564729795884D-04-.1440886961233884D-04-.8000610566205206D-04 +0.1291134218726627D-040.9653709752434816D-030.8226921401346013D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4053677357536670D+00-.1857833251535415D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1114272391270168D-03-.1798206776153138D-04-.9968672138332729D-04 +0.1608738933930258D-040.8928564729795884D-04-.1440886961233884D-04 +0.9825209093727470D-030.8407244967502225D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4056756367594502D+00 +-.1845674901271196D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1247774371156127D-03 +0.2013651551363927D-040.1114272391270168D-03-.1798206776153138D-04 +-.9968672138332729D-040.1608738933930258D-040.9997580781803323D-03 +0.8589200732350710D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4059550813249528D+00-.1834412856454672D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1400760388416475D-03-.2260539561018954D-04 +-.1247774371156127D-030.2013651551363927D-040.1114272391270168D-03 +-.1798206776153138D-040.1017082922445208D-020.8772800665956083D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4062087079073467D+00-.1823982872836648D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +-.1577525118210161D-030.2545801528730057D-040.1400760388416475D-03 +-.2260539561018954D-04-.1247774371156127D-030.2013651551363927D-04 +0.1034495885158160D-020.8958056817963518D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4064389073572802D+00 +-.1814325229964734D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1783582025510641D-03 +-.2878335054539225D-04-.1577525118210161D-030.2545801528730057D-04 +0.1400760388416475D-03-.2260539561018954D-040.1051997411532808D-02 +0.9144981318098186D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4066478467959349D+00-.1805384405054882D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-04-.2026106452901065D-030.3269719667613051D-04 +0.1783582025510641D-03-.2878335054539225D-04-.1577525118210161D-03 +0.2545801528730057D-040.1069587949016678D-020.9333586376667711D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4068374910705764D+00-.1797108773373967D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2026106452901065D-03 +0.3269719667613051D-040.1783582025510641D-03-.2878335054539225D-04 +0.1087267947302331D-020.9523884285067672D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4070096220544382D+00 +-.1789450332429918D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-04-.2661733971656183D-03 +0.4295491929664661D-040.2314578281220545D-03-.3735253948528030D-04 +-.2026106452901065D-030.3269719667613051D-040.1105037858338542D-02 +0.9715887416290131D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4071658560244203D+00-.1782364447603602D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.3085010747974997D-03-.4978573708705348D-04 +-.2661733971656183D-030.4295491929664661D-040.2314578281220545D-03 +-.3735253948528030D-040.1122898136341541D-020.9909608225435285D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4073076593221184D+00-.1775809617149684D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +-.3608796739011819D-030.5823856716447153D-040.3085010747974997D-03 +-.4978573708705348D-04-.2661733971656183D-030.4295491929664661D-04 +0.1140849237806308D-020.1010505925022613D-03-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4074363624794680D+00 +-.1769747254747372D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.4268045368517673D-03 +-.6887748599647970D-04-.3608796739011819D-030.5823856716447153D-04 +0.3085010747974997D-03-.4978573708705348D-040.1158891621517917D-02 +0.1030225311152631D-030.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4075531729692349D+00-.1764141488001286D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-03-.5114288231753483D-030.8253410768848127D-04 +0.4268045368517673D-03-.6887748599647970D-04-.3608796739011819D-03 +0.5823856716447153D-040.1177025748562945D-020.1050120251386102D-03 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4076591867222681D+00-.1758958971482033D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.6226054234808307D-03-.1004757274921541D-03-.5114288231753483D-03 +0.8253410768848127D-040.4268045368517673D-03-.6887748599647970D-04 +0.1195252082340932D-020.1070192024594111D-030.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4077553985374401D+00 +-.1754168713059499D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-03-.7727812230406976D-03 +0.1247110170406046D-030.6226054234808307D-03-.1004757274921541D-03 +-.5114288231753483D-030.8253410768848127D-040.1213571088575899D-02 +0.1090441918119028D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4078427114962225D+00-.1749741912422772D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.9826448017570867D-03-.1585786882018169D-03 +-.7727812230406976D-030.1247110170406046D-030.6226054234808307D-03 +-.1004757274921541D-030.1231983235327929D-020.1110871227827559D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4079219454815874D+00-.1745651810802267D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +-.1288661285438060D-020.2079634633143379D-030.9826448017570867D-03 +-.1585786882018169D-03-.7727812230406976D-030.1247110170406046D-03 +0.1250488993004788D-020.1131481258164096D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4079938448901613D+00 +-.1741873551014634D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1760064559812291D-02 +-.2840382695216640D-03-.1288661285438060D-020.2079634633143379D-03 +0.9826448017570867D-03-.1585786882018169D-030.1269088834373626D-02 +0.1152273322204408D-030.9826448017572174D-03-.1585786882018380D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4080590856170763D+00-.1738384047041783D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-03-.2541776982553532D-020.4101905987536608D-03 +0.1760064559812291D-02-.2840382695216640D-03-.1288661285438060D-02 +0.2079634633143379D-030.1287783234572715D-020.1173248741709648D-03 +-.1288661285438230D-020.2079634633143654D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4081182813846022D+00-.1735161862434064D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.3980741565709701D-02-.6424099272004710D-03-.2541776982553532D-02 +0.4101905987536608D-030.1760064559812291D-02-.2840382695216640D-03 +0.1306572671123266D-020.1194408847180681D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4081719894782467D+00 +-.1732187096895809D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-02-.7089509216132070D-02 +0.1144101174176702D-020.3980741565709701D-02-.6424099272004710D-03 +-.2541776982553532D-020.4101905987536608D-030.1325457623941280D-02 +0.1215754977912746D-03-.2541776982554263D-020.4101905987537787D-03 +0.1760064559812521D-02-.2840382695217011D-03-.1288661285438230D-02 +0.2079634633143654D-030.9826448017572174D-03-.1585786882018380D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4082207159474594D+00-.1729441280470915D-01-.6393452627818429D-01 +0.1031771937313455D-010.1597157490519900D-01-.2577484145293042D-02 +-.7089509216132070D-020.1144101174176702D-020.3980741565709701D-02 +-.6424099272004710D-030.1344438575349479D-020.1237288482050448D-03 +0.3980741565709959D-02-.6424099272005126D-03-.2541776982554263D-02 +0.4101905987537787D-030.1760064559812521D-02-.2840382695217011D-03 +-.1288661285438230D-020.2079634633143654D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4082649203222606D+00-.1726907274797979D-01 +-.6393452627818429D-010.1031771937313455D-010.1597157490519900D-01 +-.2577484145293042D-02-.7089509216132070D-020.1144101174176702D-02 +0.1363516010089288D-020.1259010716643076D-03-.7089509216132388D-02 +0.1144101174176753D-020.3980741565709959D-02-.6424099272005126D-03 +-.2541776982554263D-020.4101905987537787D-030.1760064559812521D-02 +-.2840382695217011D-03-.1288661285438230D-020.2079634633143654D-03 +0.9826448017572174D-03-.1585786882018380D-03-.7727812230408974D-03 +0.1247110170406368D-030.6226054234809117D-03-.1004757274921672D-03 +-.5114288231755168D-030.8253410768850847D-040.4268045368520104D-03 +-.6887748599651892D-04-.3608796739013979D-030.5823856716450639D-04 +0.3085010747980624D-03-.4978573708714430D-04-.2661733971656788D-03 +0.4295491929665637D-040.2314578281220329D-03-.3735253948527681D-04 +-.2026106452901076D-030.3269719667613068D-040.1783582025511267D-03 +-.2878335054540236D-04-.1577525118211425D-030.2545801528732096D-04 +0.1400760388418106D-03-.2260539561021587D-04-.1247774371157844D-03 +0.2013651551366699D-040.1114272391272199D-03-.1798206776156415D-04 +-.9968672138364864D-040.1608738933935444D-040.8928564729752786D-04 +-.1440886961226929D-04-.8000610566205314D-040.1291134218726644D-04 +0.7167060586276605D-04-.1156616372469904D-04-.6413319184916952D-04 +0.1034977991584680D-040.5727272713271265D-04-.9242641819512053D-05 +-.5098776122625716D-040.8228377410789080D-050.4519256146756725D-04 +-.7293151198878877D-05-.3981401266047105D-040.6425163892851680D-05 +0.3478916893609630D-04-.5614257322333374D-05-.3006329973746788D-04 +0.4851599099553577D-050.2558831255668139D-04-.4129428081521270D-05 +-.2132146425429693D-040.3440846403443515D-050.1722429384947072D-04 +-.2779647252972395D-05-.1326172498198105D-040.2140170026010777D-05 +0.9401297415863014D-05-.1517176307183306D-05-.5612495043042305D-05 +0.9057414234252119D-060.1866143715512185D-05-.3011572664637594D-06 +0.1866143715712640D-05-.3011572664961087D-06-.5612495043095234D-05 +0.9057414234337534D-060.9401297415583386D-05-.1517176307138179D-05 +-.1326172498190355D-040.2140170025998270D-050.1722429384915639D-04 +-.2779647252921669D-05-.2132146425430071D-040.3440846403444125D-05 +0.2558831255660659D-04-.4129428081509198D-05-.3006329973748652D-04 +0.4851599099556584D-050.3478916893617300D-04-.5614257322345751D-05 +-.3981401266032415D-040.6425163892827973D-050.4519256146769957D-04 +-.7293151198900231D-05-.5098776122600387D-040.8228377410748204D-05 +0.5727272713271211D-04-.9242641819511967D-05-.6413319184882657D-04 +0.1034977991579146D-040.7167060586256731D-04-.1156616372466696D-04 +-.8000610566205206D-040.1291134218726627D-040.8928564729795884D-04 +-.1440886961233884D-04-.9968672138332729D-040.1608738933930258D-04 +0.1114272391270168D-03-.1798206776153138D-04-.1247774371156127D-03 +0.2013651551363927D-040.1400760388416475D-03-.2260539561018954D-04 +-.1577525118210161D-030.2545801528730057D-040.1783582025510641D-03 +-.2878335054539225D-04-.2026106452901065D-030.3269719667613051D-04 +0.2314578281220545D-03-.3735253948528030D-04-.2661733971656183D-03 +0.4295491929664661D-040.3085010747974997D-03-.4978573708705348D-04 +-.3608796739011819D-030.5823856716447153D-040.4268045368517673D-03 +-.6887748599647970D-04-.5114288231753483D-030.8253410768848127D-04 +0.6226054234808307D-03-.1004757274921541D-03-.7727812230406976D-03 +0.1247110170406046D-030.9826448017570867D-03-.1585786882018169D-03 +-.1288661285438060D-020.2079634633143379D-030.1760064559812291D-02 +-.2840382695216640D-03-.2541776982553532D-020.4101905987536608D-03 +0.3980741565709701D-02-.6424099272004710D-03-.7089509216132070D-02 +0.1144101174176702D-020.1597157490519900D-01-.2577484145293042D-02 +-.6393452627818429D-010.1031771937313455D-01-.4083050198919414D+00 +-.1724569180949983D-01-.6393452627818429D-010.1031771937313455D-01 +0.1597157490519900D-01-.2577484145293042D-020.1382690415332871D-02 +0.1280923047700254D-030.1597157490519940D-01-.2577484145293108D-02 +-.7089509216132388D-020.1144101174176753D-020.3980741565709959D-02 +-.6424099272005126D-03-.2541776982554263D-020.4101905987537787D-03 +0.1760064559812521D-02-.2840382695217011D-03-.1288661285438230D-02 +0.2079634633143654D-030.9826448017572174D-03-.1585786882018380D-03 +-.7727812230408974D-030.1247110170406368D-030.6226054234809117D-03 +-.1004757274921672D-03-.5114288231755168D-030.8253410768850847D-04 +0.4268045368520104D-03-.6887748599651892D-04-.3608796739013979D-03 +0.5823856716450639D-040.3085010747980624D-03-.4978573708714430D-04 +-.2661733971656788D-030.4295491929665637D-040.2314578281220329D-03 +-.3735253948527681D-04-.2026106452901076D-030.3269719667613068D-04 +0.1783582025511267D-03-.2878335054540236D-04-.1577525118211425D-03 +0.2545801528732096D-040.1400760388418106D-03-.2260539561021587D-04 +-.1247774371157844D-030.2013651551366699D-040.1114272391272199D-03 +-.1798206776156415D-04-.9968672138364864D-040.1608738933935444D-04 +0.8928564729752786D-04-.1440886961226929D-04-.8000610566205314D-04 +0.1291134218726644D-040.7167060586276605D-04-.1156616372469904D-04 +-.6413319184916952D-040.1034977991584680D-040.5727272713271265D-04 +-.9242641819512053D-05-.5098776122625716D-040.8228377410789080D-05 +0.4519256146756725D-04-.7293151198878877D-05-.3981401266047105D-04 +0.6425163892851680D-050.3478916893609630D-04-.5614257322333374D-05 +-.3006329973746788D-040.4851599099553577D-050.2558831255668139D-04 +-.4129428081521270D-05-.2132146425429693D-040.3440846403443515D-05 +0.1722429384947072D-04-.2779647252972395D-05-.1326172498198105D-04 +0.2140170026010777D-050.9401297415863014D-05-.1517176307183306D-05 +-.5612495043042305D-050.9057414234252119D-060.1866143715512185D-05 +-.3011572664637594D-060.1866143715712640D-05-.3011572664961087D-06 +-.5612495043095234D-050.9057414234337534D-060.9401297415583386D-05 +-.1517176307138179D-05-.1326172498190355D-040.2140170025998270D-05 +0.1722429384915639D-04-.2779647252921669D-05-.2132146425430071D-04 +0.3440846403444125D-050.2558831255660659D-04-.4129428081509198D-05 +-.3006329973748652D-040.4851599099556584D-050.3478916893617300D-04 +-.5614257322345751D-05-.3981401266032415D-040.6425163892827973D-05 +0.4519256146769957D-04-.7293151198900231D-05-.5098776122600387D-04 +0.8228377410748204D-050.5727272713271211D-04-.9242641819511967D-05 +-.6413319184882657D-040.1034977991579146D-040.7167060586256731D-04 +-.1156616372466696D-04-.8000610566205206D-040.1291134218726627D-04 +0.8928564729795884D-04-.1440886961233884D-04-.9968672138332729D-04 +0.1608738933930258D-040.1114272391270168D-03-.1798206776153138D-04 +-.1247774371156127D-030.2013651551363927D-040.1400760388416475D-03 +-.2260539561018954D-04-.1577525118210161D-030.2545801528730057D-04 +0.1783582025510641D-03-.2878335054539225D-04-.2026106452901065D-03 +0.3269719667613051D-040.2314578281220545D-03-.3735253948528030D-04 +-.2661733971656183D-030.4295491929664661D-040.3085010747974997D-03 +-.4978573708705348D-04-.3608796739011819D-030.5823856716447153D-04 +0.4268045368517673D-03-.6887748599647970D-04-.5114288231753483D-03 +0.8253410768848127D-040.6226054234808307D-03-.1004757274921541D-03 +-.7727812230406976D-030.1247110170406046D-030.9826448017570867D-03 +-.1585786882018169D-03-.1288661285438060D-020.2079634633143379D-03 +0.1760064559812291D-02-.2840382695216640D-03-.2541776982553532D-02 +0.4101905987536608D-030.3980741565709701D-02-.6424099272004710D-03 +-.7089509216132070D-020.1144101174176702D-020.1597157490519900D-01 +-.2577484145293042D-02-.6393452627818429D-010.1031771937313455D-01 +-.4083413935873786D+00-.1722412253413513D-01-.6393452627818429D-01 +0.1031771937313455D-010.1401962280695231D-020.1303026850247933D-03 +-.6393452627818492D-010.1031771937313466D-010.1597157490519940D-01 +-.2577484145293108D-02-.7089509216132388D-020.1144101174176753D-02 +0.3980741565709959D-02-.6424099272005126D-03-.2541776982554263D-02 +0.4101905987537787D-030.1760064559812521D-02-.2840382695217011D-03 +-.1288661285438230D-020.2079634633143654D-030.9826448017572174D-03 +-.1585786882018380D-03-.7727812230408974D-030.1247110170406368D-03 +0.6226054234809117D-03-.1004757274921672D-03-.5114288231755168D-03 +0.8253410768850847D-040.4268045368520104D-03-.6887748599651892D-04 +-.3608796739013979D-030.5823856716450639D-040.3085010747980624D-03 +-.4978573708714430D-04-.2661733971656788D-030.4295491929665637D-04 +0.2314578281220329D-03-.3735253948527681D-04-.2026106452901076D-03 +0.3269719667613068D-040.1783582025511267D-03-.2878335054540236D-04 +-.1577525118211425D-030.2545801528732096D-040.1400760388418106D-03 +-.2260539561021587D-04-.1247774371157844D-030.2013651551366699D-04 +0.1114272391272199D-03-.1798206776156415D-04-.9968672138364864D-04 +0.1608738933935444D-040.8928564729752786D-04-.1440886961226929D-04 +-.8000610566205314D-040.1291134218726644D-040.7167060586276605D-04 +-.1156616372469904D-04-.6413319184916952D-040.1034977991584680D-04 +0.5727272713271265D-04-.9242641819512053D-05-.5098776122625716D-04 +0.8228377410789080D-050.4519256146756725D-04-.7293151198878877D-05 +-.3981401266047105D-040.6425163892851680D-050.3478916893609630D-04 +-.5614257322333374D-05-.3006329973746788D-040.4851599099553577D-05 +0.2558831255668139D-04-.4129428081521270D-05-.2132146425429693D-04 +0.3440846403443515D-050.1722429384947072D-04-.2779647252972395D-05 +-.1326172498198105D-040.2140170026010777D-050.9401297415863014D-05 +-.1517176307183306D-05-.5612495043042305D-050.9057414234252119D-06 +0.1866143715512185D-05-.3011572664637594D-060.1866143715712640D-05 +-.3011572664961087D-06-.5612495043095234D-050.9057414234337534D-06 +0.9401297415583386D-05-.1517176307138179D-05-.1326172498190355D-04 +0.2140170025998270D-050.1722429384915639D-04-.2779647252921669D-05 +-.2132146425430071D-040.3440846403444125D-050.2558831255660659D-04 +-.4129428081509198D-05-.3006329973748652D-040.4851599099556584D-05 +0.3478916893617300D-04-.5614257322345751D-05-.3981401266032415D-04 +0.6425163892827973D-050.4519256146769957D-04-.7293151198900231D-05 +-.5098776122600387D-040.8228377410748204D-050.5727272713271211D-04 +-.9242641819511967D-05-.6413319184882657D-040.1034977991579146D-04 +0.7167060586256731D-04-.1156616372466696D-04-.8000610566205206D-04 +0.1291134218726627D-040.8928564729795884D-04-.1440886961233884D-04 +-.9968672138332729D-040.1608738933930258D-040.1114272391270168D-03 +-.1798206776153138D-04-.1247774371156127D-030.2013651551363927D-04 +0.1400760388416475D-03-.2260539561018954D-04-.1577525118210161D-03 +0.2545801528730057D-040.1783582025510641D-03-.2878335054539225D-04 +-.2026106452901065D-030.3269719667613051D-040.2314578281220545D-03 +-.3735253948528030D-04-.2661733971656183D-030.4295491929664661D-04 +0.3085010747974997D-03-.4978573708705348D-04-.3608796739011819D-03 +0.5823856716447153D-040.4268045368517673D-03-.6887748599647970D-04 +-.5114288231753483D-030.8253410768848127D-040.6226054234808307D-03 +-.1004757274921541D-03-.7727812230406976D-030.1247110170406046D-03 +0.9826448017570867D-03-.1585786882018169D-03-.1288661285438060D-02 +0.2079634633143379D-030.1760064559812291D-02-.2840382695216640D-03 +-.2541776982553532D-020.4101905987536608D-030.3980741565709701D-02 +-.6424099272004710D-03-.7089509216132070D-020.1144101174176702D-02 +0.1597157490519900D-01-.2577484145293042D-02-.6393452627818429D-01 +0.1031771937313455D-01-.4083743855043928D+00-.1720422819797903D-01 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/HB/west0067.rua b/liboctave/UMFPACK/UMFPACK/Demo/HB/west0067.rua new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/HB/west0067.rua @@ -0,0 +1,115 @@ +1U CAVETT PROBLEM WITH 5 COMPONENTS ( CHEM. ENG. FROM WESTERBERG ) WEST0067 + 111 7 30 74 0 +RUA 67 67 294 0 +(10I8) (10I8) (4E20.12) + 1 11 15 19 23 27 30 35 38 41 + 44 47 49 54 59 64 69 73 78 80 + 90 93 96 99 102 105 109 113 117 121 + 124 134 137 140 143 146 149 159 164 169 + 174 179 183 188 192 196 200 204 207 217 + 220 223 226 229 232 242 247 252 257 262 + 266 271 275 279 283 287 290 295 + 5 6 7 8 9 25 26 27 28 29 + 5 21 25 61 6 22 26 61 7 23 + 27 61 8 24 28 61 9 29 61 5 + 6 7 8 9 1 5 57 2 6 57 + 3 7 57 4 8 57 9 57 1 5 + 10 11 58 2 6 10 12 58 3 7 + 10 13 58 4 8 10 14 58 9 10 + 15 58 1 2 3 4 10 15 56 11 + 12 13 14 15 16 17 18 19 20 11 + 16 59 12 17 59 13 18 59 14 19 + 59 15 20 59 16 36 40 64 17 37 + 41 64 18 38 42 64 19 39 43 64 + 20 44 64 16 17 18 19 20 25 26 + 27 28 29 16 25 60 17 26 60 18 + 27 60 19 28 60 20 29 60 25 26 + 27 28 29 31 32 33 34 35 21 25 + 30 31 62 22 26 30 32 62 23 27 + 30 33 62 24 28 30 34 62 29 30 + 35 62 21 22 23 24 30 31 46 50 + 66 32 47 51 66 33 48 52 66 34 + 49 53 66 35 54 66 31 32 33 34 + 35 40 41 42 43 44 31 40 63 32 + 41 63 33 42 63 34 43 63 35 44 + 63 40 41 42 43 44 50 51 52 53 + 54 36 40 45 50 65 37 41 45 51 + 65 38 42 45 52 65 39 43 45 53 + 65 44 45 54 65 36 37 38 39 45 + 46 50 55 67 47 51 55 67 48 52 + 55 67 49 53 55 67 54 55 67 46 + 47 48 49 55 + -.278841600000E+00 -.268018600000E+00 -.232371700000E+00 -.157508200000E+00 + -.632597800000E-01 .139420800000E+00 .134009300000E+00 .116185900000E+00 + .787541100000E-01 .316298900000E-01 -.800000000000E+00 -.915953300000E+00 + .400000000000E+00 .100000000000E+01 -.800000000000E+00 -.915953300000E+00 + .400000000000E+00 .100000000000E+01 -.800000000000E+00 -.915953300000E+00 + .400000000000E+00 .100000000000E+01 -.800000000000E+00 -.915953300000E+00 + .400000000000E+00 .100000000000E+01 -.800000000000E+00 .400000000000E+00 + .100000000000E+01 .134462200000E+00 .117567900000E+00 .885926200000E-01 + .475943900000E-01 .117829100000E-01 -.834181800000E+00 .400000000000E+00 + .100000000000E+01 -.834181800000E+00 .400000000000E+00 .100000000000E+01 + -.834181800000E+00 .400000000000E+00 .100000000000E+01 -.834181800000E+00 + .400000000000E+00 .100000000000E+01 .400000000000E+00 .100000000000E+01 + .126582300000E+01 .400000000000E+00 -.126582300000E+01 .333333300000E+00 + .100000000000E+01 .101265800000E+01 .400000000000E+00 -.101265800000E+01 + .333333300000E+00 .100000000000E+01 .759493700000E+00 .400000000000E+00 + -.759493700000E+00 .333333300000E+00 .100000000000E+01 .506329100000E+00 + .400000000000E+00 -.506329100000E+00 .333333300000E+00 .100000000000E+01 + .400000000000E+00 -.253164600000E+00 .333333300000E+00 .100000000000E+01 + -.336155600000E+00 -.293919600000E+00 -.221481500000E+00 -.118986000000E+00 + .100000000000E+01 .666666700000E+00 .100000000000E+01 -.207175900000E+00 + -.214039200000E+00 -.214420600000E+00 -.198676800000E+00 -.165687400000E+00 + .124305500000E+00 .128423500000E+00 .128652400000E+00 .119206100000E+00 + .994124600000E-01 -.100000000000E+01 .600000000000E+00 .100000000000E+01 + -.100000000000E+01 .600000000000E+00 .100000000000E+01 -.100000000000E+01 + .600000000000E+00 .100000000000E+01 -.100000000000E+01 .600000000000E+00 + .100000000000E+01 -.100000000000E+01 .600000000000E+00 .100000000000E+01 + .450000000000E+00 -.958318700000E+00 .500000000000E+00 .100000000000E+01 + .450000000000E+00 -.958318700000E+00 .500000000000E+00 .100000000000E+01 + .450000000000E+00 -.958318700000E+00 .500000000000E+00 .100000000000E+01 + .450000000000E+00 -.958318700000E+00 .500000000000E+00 .100000000000E+01 + .450000000000E+00 .500000000000E+00 .100000000000E+01 -.207098600000E+00 + -.223299700000E+00 -.228626400000E+00 -.202452800000E+00 -.138522600000E+00 + -.207098600000E+00 -.223299700000E+00 -.228626400000E+00 -.202452800000E+00 + -.138522600000E+00 -.105000000000E+01 -.105000000000E+01 .100000000000E+01 + -.105000000000E+01 -.105000000000E+01 .100000000000E+01 -.105000000000E+01 + -.105000000000E+01 .100000000000E+01 -.105000000000E+01 -.105000000000E+01 + .100000000000E+01 -.105000000000E+01 -.105000000000E+01 .100000000000E+01 + .814744900000E-01 .978901500000E-01 .113160800000E+00 .115055500000E+00 + .924190900000E-01 .905272100000E-01 .108766800000E+00 .125734200000E+00 + .127839400000E+00 .102687900000E+00 .156739800000E+01 .650000000000E+00 + -.156739800000E+01 .722222200000E+00 .100000000000E+01 .125391800000E+01 + .650000000000E+00 -.125391800000E+01 .722222200000E+00 .100000000000E+01 + .940438900000E+00 .650000000000E+00 -.940438900000E+00 .722222200000E+00 + .100000000000E+01 .626959200000E+00 .650000000000E+00 -.626959200000E+00 + .722222200000E+00 .100000000000E+01 .650000000000E+00 -.313479600000E+00 + .722222200000E+00 .100000000000E+01 -.278841600000E+00 -.268018600000E+00 + -.232371700000E+00 -.157508200000E+00 .100000000000E+01 .250000000000E+00 + -.824224800000E+00 .500000000000E+00 .100000000000E+01 .250000000000E+00 + -.824224800000E+00 .500000000000E+00 .100000000000E+01 .250000000000E+00 + -.824224800000E+00 .500000000000E+00 .100000000000E+01 .250000000000E+00 + -.824224800000E+00 .500000000000E+00 .100000000000E+01 .250000000000E+00 + .500000000000E+00 .100000000000E+01 -.158162600000E+00 -.194771100000E+00 + -.230391700000E+00 -.236284500000E+00 -.180390000000E+00 -.158162600000E+00 + -.194771100000E+00 -.230391700000E+00 -.236284500000E+00 -.180390000000E+00 + -.972222200000E+00 -.972222200000E+00 .100000000000E+01 -.972222200000E+00 + -.972222200000E+00 .100000000000E+01 -.972222200000E+00 -.972222200000E+00 + .100000000000E+01 -.972222200000E+00 -.972222200000E+00 .100000000000E+01 + -.972222200000E+00 -.972222200000E+00 .100000000000E+01 .532286400000E-01 + .757454200000E-01 .106102800000E+00 .133387800000E+00 .131535300000E+00 + -.106457300000E+00 -.151490800000E+00 -.212205600000E+00 -.266775700000E+00 + -.263070600000E+00 .186335400000E+01 .472222200000E+00 -.186335400000E+01 + -.944444400000E+00 .100000000000E+01 .149068300000E+01 .472222200000E+00 + -.149068300000E+01 -.944444400000E+00 .100000000000E+01 .111801200000E+01 + .472222200000E+00 -.111801200000E+01 -.944444400000E+00 .100000000000E+01 + .745341600000E+00 .472222200000E+00 -.745341600000E+00 -.944444400000E+00 + .100000000000E+01 .472222200000E+00 -.372670800000E+00 -.944444400000E+00 + .100000000000E+01 -.206995400000E+00 -.235646900000E+00 -.247567500000E+00 + -.207487300000E+00 .100000000000E+01 .186335400000E+01 .444444400000E+00 + -.186335400000E+01 .100000000000E+01 .149068300000E+01 .444444400000E+00 + -.149068300000E+01 .100000000000E+01 .111801200000E+01 .444444400000E+00 + -.111801200000E+01 .100000000000E+01 .745341600000E+00 .444444400000E+00 + -.745341600000E+00 .100000000000E+01 .444444400000E+00 -.372670800000E+00 + .100000000000E+01 -.144335400000E+00 -.191855700000E+00 -.242149800000E+00 + -.254119300000E+00 .100000000000E+01 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/Makefile b/liboctave/UMFPACK/UMFPACK/Demo/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/Makefile @@ -0,0 +1,165 @@ +#------------------------------------------------------------------------------- +# compile the UMFPACK demos (for GNU make and original make) +#------------------------------------------------------------------------------- + +# UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +# All Rights Reserved. See ../Doc/License for License. + +all: umfpack_di_demo umfpack_zi_demo umfpack_dl_demo umfpack_zl_demo \ + umfpack_simple + +include ../Make/Make.include + +C = $(CC) $(CFLAGS) $(CONFIG) -I../Include -I../../AMD/Include + +INC = ../Include/umfpack.h ../../AMD/Include/amd.h + +../Lib/libumfpack.a: + ( cd ../Source ; make ) + +../../AMD/Lib/libamd.a: + ( cd ../../AMD/Source ; make ) + +UMFPACK = ../Lib/libumfpack.a ../../AMD/Lib/libamd.a + +#------------------------------------------------------------------------------- +# Create the demo programs, run them, and compare the output +#------------------------------------------------------------------------------- + +dist: umfpack_di_demo.c umfpack_dl_demo.c umfpack_zi_demo.c umfpack_zl_demo.c + +umfpack_simple: umfpack_simple.c $(INC) $(UMFPACK) + $(C) -o umfpack_simple umfpack_simple.c $(UMFPACK) $(LIB) + ./umfpack_simple + +# the GNU rules are simpler: +# umfpack_%_demo.c: umfpack_xx_demo.c umfpack_%_demo.sed +# - sed -f umfpack_$*_demo.sed < umfpack_xx_demo.c > umfpack_$*_demo.c +# +# umfpack_%_demo: umfpack_%_demo.c $(INC) $(UMFPACK) +# $(C) -o umfpack_$*_demo umfpack_$*_demo.c $(UMFPACK) $(LIB) +# ./umfpack_$*_demo > my_umfpack_$*_demo.out + +# but do this via brute-force, so we can use just a single Makefile: + +# double-precision, int verion: +umfpack_di_demo.c: umfpack_xx_demo.c umfpack_di_demo.sed + - sed -f umfpack_di_demo.sed < umfpack_xx_demo.c > umfpack_di_demo.c + +umfpack_di_demo: umfpack_di_demo.c $(INC) $(UMFPACK) + $(C) -o umfpack_di_demo umfpack_di_demo.c $(UMFPACK) $(LIB) + ./umfpack_di_demo > my_umfpack_di_demo.out + - diff umfpack_di_demo.out my_umfpack_di_demo.out + +# double-precision, long verion: +umfpack_dl_demo.c: umfpack_xx_demo.c umfpack_dl_demo.sed + - sed -f umfpack_dl_demo.sed < umfpack_xx_demo.c > umfpack_dl_demo.c + +umfpack_dl_demo: umfpack_dl_demo.c $(INC) $(UMFPACK) + $(C) -o umfpack_dl_demo umfpack_dl_demo.c $(UMFPACK) $(LIB) + ./umfpack_dl_demo > my_umfpack_dl_demo.out + - diff umfpack_dl_demo.out my_umfpack_dl_demo.out + +# complex, int verion: +umfpack_zi_demo.c: umfpack_xx_demo.c umfpack_zi_demo.sed + - sed -f umfpack_zi_demo.sed < umfpack_xx_demo.c > umfpack_zi_demo.c + +umfpack_zi_demo: umfpack_zi_demo.c $(INC) $(UMFPACK) + $(C) -o umfpack_zi_demo umfpack_zi_demo.c $(UMFPACK) $(LIB) + ./umfpack_zi_demo > my_umfpack_zi_demo.out + - diff umfpack_zi_demo.out my_umfpack_zi_demo.out + +# complex, long verion: +umfpack_zl_demo.c: umfpack_xx_demo.c umfpack_zl_demo.sed + - sed -f umfpack_zl_demo.sed < umfpack_xx_demo.c > umfpack_zl_demo.c + +umfpack_zl_demo: umfpack_zl_demo.c $(INC) $(UMFPACK) + $(C) -o umfpack_zl_demo umfpack_zl_demo.c $(UMFPACK) $(LIB) + ./umfpack_zl_demo > my_umfpack_zl_demo.out + - diff umfpack_zl_demo.out my_umfpack_zl_demo.out + +#------------------------------------------------------------------------------- +# create a demo program that reads in Harwell/Boeing matrices, and run it +#------------------------------------------------------------------------------- + +# the output of "make hb" is in the file umf4.out +hb: $(UMFPACK) umf4 readhb readhb_nozeros readhb_size + - ./readhb_nozeros < HB/can_24.psa > tmp/A + - ./readhb_size < HB/can_24.psa > tmp/Asize + - ./umf4 + - ./readhb_nozeros < HB/west0067.rua > tmp/A + - ./readhb_size < HB/west0067.rua > tmp/Asize + - ./umf4 + - ./readhb_nozeros < HB/fs_183_6.rua > tmp/A + - ./readhb_size < HB/fs_183_6.rua > tmp/Asize + - ./umf4 + - ./readhb < HB/fs_183_6.rua > tmp/A + - ./readhb_size < HB/fs_183_6.rua > tmp/Asize + - ./umf4 + - ./readhb < HB/arc130.rua > tmp/A + - ./readhb_size < HB/arc130.rua > tmp/Asize + - ./umf4 + - ./readhb_nozeros < HB/arc130.rua > tmp/A + - ./readhb_size < HB/arc130.rua > tmp/Asize + - ./umf4 + - ./readhb_nozeros < HB/arc130.rua > tmp/A + - ./readhb_size < HB/arc130.rua > tmp/Asize + - ./umf4 a 1e-6 + +umf4: umf4.c $(UMFPACK) + $(C) -o umf4 umf4.c $(UMFPACK) $(LIB) + +readhb: readhb.f + $(F77) $(F77FLAGS) -o readhb readhb.f $(F77LIB) + +readhb_size: readhb_size.f + $(F77) $(F77FLAGS) -o readhb_size readhb_size.f $(F77LIB) + +readhb_nozeros: readhb_nozeros.f + $(F77) $(F77FLAGS) -o readhb_nozeros readhb_nozeros.f $(F77LIB) + +#------------------------------------------------------------------------------- +# compile the FORTRAN interface and demo +#------------------------------------------------------------------------------- + +fortran: $(UMFPACK) umf4hb.f umf4_f77wrapper.o umf4zhb.f umf4_f77zwrapper.o $(UMFPACK) + $(F77) $(F77FLAGS) -o umf4hb umf4hb.f umf4_f77wrapper.o \ + $(UMFPACK) $(LIB) + - ./umf4hb < HB/west0067.rua > my_umf4hb.out + - diff my_umf4hb.out umf4hb.out + $(F77) $(F77FLAGS) -o umf4zhb umf4zhb.f umf4_f77zwrapper.o \ + $(UMFPACK) $(LIB) + - ./umf4zhb < HB/qc324.cua > my_umf4zhb.out + - diff my_umf4zhb.out umf4zhb.out + +fortran64: $(UMFPACK) umf4hb64.f umf4_f77wrapper64.o umf4_f77zwrapper64.o $(UMFPACK) + $(F77) $(F77FLAGS) -o umf4hb64 umf4hb64.f umf4_f77wrapper64.o \ + $(UMFPACK) $(LIB) + - ./umf4hb64 < HB/west0067.rua > my_umf4hb64.out + - diff my_umf4hb64.out umf4hb64.out + +umf4_f77wrapper.o: umf4_f77wrapper.c $(INC) + $(C) -c umf4_f77wrapper.c -o umf4_f77wrapper.o + +umf4_f77zwrapper.o: umf4_f77zwrapper.c $(INC) + $(C) -c umf4_f77zwrapper.c -o umf4_f77zwrapper.o + +umf4_f77wrapper64.o: umf4_f77wrapper.c $(INC) + $(C) -DDLONG -c umf4_f77wrapper.c -o umf4_f77wrapper64.o + +umf4_f77zwrapper64.o: umf4_f77zwrapper.c $(INC) + $(C) -DDLONG -c umf4_f77zwrapper.c -o umf4_f77zwrapper64.o + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) umfpack_simple a.out + - $(RM) umfpack_di_demo my_umfpack_di_demo.out + - $(RM) umfpack_dl_demo my_umfpack_dl_demo.out + - $(RM) umfpack_zi_demo my_umfpack_zi_demo.out + - $(RM) umfpack_zl_demo my_umfpack_zl_demo.out + - $(RM) umf4hb umf4zhb *.umf my_umf4hb.out + - $(RM) umf4hb64 my_umf4hb64.out my_umf4zhb.out + - $(RM) umf4 readhb readhb_nozeros readhb_size tmp/* diff --git a/liboctave/UMFPACK/UMFPACK/Demo/readhb.f b/liboctave/UMFPACK/UMFPACK/Demo/readhb.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/readhb.f @@ -0,0 +1,115 @@ +c======================================================================= +c== readhb ============================================================= +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c readhb: +c read a sparse matrix in the Harwell/Boeing format and +c output a matrix in triplet format. +c +c usage (for example): +c +c in a Unix shell: +c readhb < HB/arc130.rua > tmp/A +c +c Then, in MATLAB, you can do the following: +c >> load tmp/A +c >> A = spconvert (A) ; +c >> spy (A) + + integer nzmax, nmax + parameter (nzmax = 10000000, nmax = 250000) + integer Ptr (nmax), Index (nzmax), n, nz, totcrd, ptrcrd, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs, row, col, p + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + logical sym + double precision Value (nzmax), skew + character rhstyp*3 + integer nzrhs, nel + + integer ne, nnz + +c----------------------------------------------------------------------- + +c read header information from Harwell/Boeing matrix + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp,nrhs,nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + skew = 0.0 + if (type (2:2) .eq. 'Z' .or. type (2:2) .eq. 'z') skew = -1.0 + if (type (2:2) .eq. 'S' .or. type (2:2) .eq. 's') skew = 1.0 + sym = skew .ne. 0.0 + + write (0, 31) key +31 format ('Matrix key: ', a8) + + n = max (nrow, ncol) + + if (n .ge. nmax .or. nz .gt. nzmax) then + write (0, *) 'Matrix too big!' + write (0, *) '(recompile readhb.f with larger nzmax, nmax)' + stop + endif + + read (5, ptrfmt, err = 998) (Ptr (p), p = 1, ncol+1) + read (5, indfmt, err = 998) (Index (p), p = 1, nz) + + do 55 col = ncol+2, n+1 + Ptr (col) = Ptr (ncol+1) +55 continue + +c read the values + if (valcrd .gt. 0) then + read (5, valfmt, err = 998) (Value (p), p = 1, nz) + else + do 50 p = 1, nz + Value (p) = 1 +50 continue + endif + +c create the triplet form of the input matrix + + ne = 0 + nnz = 0 + do 100 col = 1, n + do 90 p = Ptr (col), Ptr (col+1) - 1 + row = Index (p) + + ne = ne + 1 + nnz = nnz + 1 + write (6, 200) row, col, Value (p) + + if (sym .and. row .ne. col) then + ne = ne + 1 + if (Value (p) .ne. 0) then + nnz = nnz + 1 + write (6, 200) col, row, skew * Value (p) + endif + endif + +90 continue +100 continue +200 format (2i7, e30.18e3) + +c write (0,*) 'Number of entries: ',ne,' True nonzeros: ', nnz + stop + +998 write (0,*) 'Read error: Harwell/Boeing matrix' + stop + end diff --git a/liboctave/UMFPACK/UMFPACK/Demo/readhb_nozeros.f b/liboctave/UMFPACK/UMFPACK/Demo/readhb_nozeros.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/readhb_nozeros.f @@ -0,0 +1,122 @@ +c======================================================================= +c== readhb_nozeros ===================================================== +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c readhb_nozeros: +c read a sparse matrix in the Harwell/Boeing format and +c output a matrix in triplet format. +c Identical to readhb, except that this version removes explicit +c zero entries from the matrix. +c +c usage (for example): +c +c in a Unix shell: +c readhb_nozeros < HB/arc130.rua > tmp/A +c +c Then, in MATLAB, you can do the following: +c >> load tmp/A +c >> A = spconvert (A) ; +c >> spy (A) + + integer nzmax, nmax + parameter (nzmax = 10000000, nmax = 250000) + integer Ptr (nmax), Index (nzmax), n, nz, totcrd, ptrcrd, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs, row, col, p + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + logical sym + double precision Value (nzmax), skew + character rhstyp*3 + integer nzrhs, nel + + integer ne, nnz + +c----------------------------------------------------------------------- + +c read header information from Harwell/Boeing matrix + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp,nrhs,nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + skew = 0.0 + if (type (2:2) .eq. 'Z' .or. type (2:2) .eq. 'z') skew = -1.0 + if (type (2:2) .eq. 'S' .or. type (2:2) .eq. 's') skew = 1.0 + sym = skew .ne. 0.0 + + write (0, 31) key +31 format ('Matrix key: ', a8) + + n = max (nrow, ncol) + + if (n .ge. nmax .or. nz .gt. nzmax) then + write (0, *) 'Matrix too big!' + write (0, *) '(recompile readhb_nozeros.f with larger', + $ ' nzmax, nmax)' + stop + endif + + read (5, ptrfmt, err = 998) (Ptr (p), p = 1, ncol+1) + read (5, indfmt, err = 998) (Index (p), p = 1, nz) + + do 55 col = ncol+2, n+1 + Ptr (col) = Ptr (ncol+1) +55 continue + +c read the values + if (valcrd .gt. 0) then + read (5, valfmt, err = 998) (Value (p), p = 1, nz) + else + do 50 p = 1, nz + Value (p) = 1 +50 continue + endif + +c create the triplet form of the input matrix + + ne = 0 + nnz = 0 + do 100 col = 1, n + do 90 p = Ptr (col), Ptr (col+1) - 1 + row = Index (p) + +c remove zeros, to compare fairly with LU in MATLAB +c (MATLAB always removes explicit zeros) + ne = ne + 1 + if (Value (p) .ne. 0) then + nnz = nnz + 1 + write (6, 200) row, col, Value (p) + endif + + if (sym .and. row .ne. col) then + ne = ne + 1 + if (Value (p) .ne. 0) then + nnz = nnz + 1 + write (6, 200) col, row, skew * Value (p) + endif + endif + +90 continue +100 continue +200 format (2i7, e30.18e3) + +c write (0,*) 'Number of entries: ',ne,' True nonzeros: ', nnz + stop + +998 write (0,*) 'Read error: Harwell/Boeing matrix' + stop + end diff --git a/liboctave/UMFPACK/UMFPACK/Demo/readhb_size.f b/liboctave/UMFPACK/UMFPACK/Demo/readhb_size.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/readhb_size.f @@ -0,0 +1,47 @@ +c======================================================================= +c== readhb_size ======================================================== +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c readhb_size: +c read a sparse matrix in the Harwell/Boeing format and output the +c size of the matrix (# rows, # columns, and # of entries) +c +c usage (for example): +c +c readhb_size < HB/arc130.rua > tmp/Asize + + integer nz, totcrd, ptrcrd, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + character rhstyp*3 + integer nzrhs, nel + +c----------------------------------------------------------------------- + +c read header information from Harwell/Boeing matrix + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp,nrhs,nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + write (6, *) nrow, ncol, nz + stop +998 write (0, *) 'Read error' + stop + end + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/simple_compile b/liboctave/UMFPACK/UMFPACK/Demo/simple_compile new file mode 100755 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/simple_compile @@ -0,0 +1,108 @@ +#!/bin/csh + +# This one-line command compiles all of UMFPACK and the double/int demo. +# It forms a useful prototype for Microsoft Visual Studio, which does not +# have the flexibility of Unix/Linux "make". The latter can be configured +# to compile one file multiple times (as required by UMFPACK). Here, +# that requirement is solved with a single file, umf_multicompile.c. +# +# No BLAS is used here. + +cc -DDINT -DNBLAS \ + -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source \ + umfpack_di_demo.c \ + ../Source/umf_multicompile.c \ + ../Source/umf_ltsolve.c \ + ../Source/umf_utsolve.c \ + ../Source/umf_triplet.c \ + ../Source/umf_assemble.c \ + ../Source/umf_store_lu.c \ + ../Source/umfpack_solve.c \ + ../../AMD/Source/amd_1.c \ + ../../AMD/Source/amd_2.c \ + ../../AMD/Source/amd_aat.c \ + ../../AMD/Source/amd_control.c \ + ../../AMD/Source/amd_defaults.c \ + ../../AMD/Source/amd_dump.c \ + ../../AMD/Source/amd_info.c \ + ../../AMD/Source/amd_order.c \ + ../../AMD/Source/amd_post_tree.c \ + ../../AMD/Source/amd_postorder.c \ + ../../AMD/Source/amd_preprocess.c \ + ../../AMD/Source/amd_valid.c \ + ../Source/umf_2by2.c \ + ../Source/umf_analyze.c \ + ../Source/umf_apply_order.c \ + ../Source/umf_blas3_update.c \ + ../Source/umf_build_tuples.c \ + ../Source/umf_colamd.c \ + ../Source/umf_create_element.c \ + ../Source/umf_dump.c \ + ../Source/umf_extend_front.c \ + ../Source/umf_free.c \ + ../Source/umf_fsize.c \ + ../Source/umf_garbage_collection.c \ + ../Source/umf_get_memory.c \ + ../Source/umf_grow_front.c \ + ../Source/umf_init_front.c \ + ../Source/umf_is_permutation.c \ + ../Source/umf_kernel.c \ + ../Source/umf_kernel_init.c \ + ../Source/umf_kernel_wrapup.c \ + ../Source/umf_local_search.c \ + ../Source/umf_lsolve.c \ + ../Source/umf_malloc.c \ + ../Source/umf_mem_alloc_element.c \ + ../Source/umf_mem_alloc_head_block.c \ + ../Source/umf_mem_alloc_tail_block.c \ + ../Source/umf_mem_free_tail_block.c \ + ../Source/umf_mem_init_memoryspace.c \ + ../Source/umf_realloc.c \ + ../Source/umf_report_perm.c \ + ../Source/umf_report_vector.c \ + ../Source/umf_row_search.c \ + ../Source/umf_scale.c \ + ../Source/umf_scale_column.c \ + ../Source/umf_set_stats.c \ + ../Source/umf_singletons.c \ + ../Source/umf_solve.c \ + ../Source/umf_start_front.c \ + ../Source/umf_symbolic_usage.c \ + ../Source/umf_transpose.c \ + ../Source/umf_tuple_lengths.c \ + ../Source/umf_usolve.c \ + ../Source/umf_valid_numeric.c \ + ../Source/umf_valid_symbolic.c \ + ../Source/umfpack_col_to_triplet.c \ + ../Source/umfpack_defaults.c \ + ../Source/umfpack_free_numeric.c \ + ../Source/umfpack_free_symbolic.c \ + ../Source/umfpack_get_determinant.c \ + ../Source/umfpack_get_lunz.c \ + ../Source/umfpack_get_numeric.c \ + ../Source/umfpack_get_symbolic.c \ + ../Source/umfpack_load_numeric.c \ + ../Source/umfpack_load_symbolic.c \ + ../Source/umfpack_numeric.c \ + ../Source/umfpack_qsymbolic.c \ + ../Source/umfpack_report_control.c \ + ../Source/umfpack_report_info.c \ + ../Source/umfpack_report_matrix.c \ + ../Source/umfpack_report_numeric.c \ + ../Source/umfpack_report_perm.c \ + ../Source/umfpack_report_status.c \ + ../Source/umfpack_report_symbolic.c \ + ../Source/umfpack_report_triplet.c \ + ../Source/umfpack_report_vector.c \ + ../Source/umfpack_save_numeric.c \ + ../Source/umfpack_save_symbolic.c \ + ../Source/umfpack_scale.c \ + ../Source/umfpack_symbolic.c \ + ../Source/umfpack_tictoc.c \ + ../Source/umfpack_timer.c \ + ../Source/umfpack_transpose.c \ + ../Source/umfpack_triplet_to_col.c \ + -lm + +# now run the demo +./a.out diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4.c b/liboctave/UMFPACK/UMFPACK/Demo/umf4.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4.c @@ -0,0 +1,649 @@ +/* ========================================================================== */ +/* === umf4 ================================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Demo program for UMFPACK. Reads in a triplet-form matrix in the + * directory tmp/A, whose size and # of nonzeros are in the file tmp/Asize. + * Then calls UMFPACK to analyze, factor, and solve the system. + * + * Syntax: + * + * umf4 default "auto" strategy, 1-norm row scaling + * umf4 a default "auto" strategy, 1-norm row scaling + * umf4 u unsymmetric strategy, 1-norm row scaling + * umf4 s symmetric strategy, 1-norm row scaling + * umf4 2 2-by-2 strategy, maxnorm row scaling + * umf4 A default "auto" strategy, maxnorm row scaling + * umf4 U unsymmetric strategy, maxnorm row scaling + * umf4 S symmetric strategy, maxnorm row scaling + * umf4 T 2-by-2 strategy , maxnorm row scaling + * + * To test a matrix in the Harwell/Boeing format, do the following: + * + * readhb < HB/arc130.rua > tmp/A + * readhb_size < HB/arc130.rua > tmp/Asize + * umf4 + * + * The above options do not drop any nonzero entry in L or U. To compute an + * incomplete factorization, you can add a second argument to give the drop + * tolerance. Entries less than or equal to the drop tolerance are then + * removed from L and U during factorization, unless dropping those entries + * does not save any memory space. For example: + * + * umf4 a 1e-6 default "auto" strategy, 1-norm row scaling, + * drop tolerance of 1e-6. + * + * Note that adding a drop tolerance can lead to an apparent (but not real) + * increase in peak memory usage. This is illustrated in the arc130.rua + * matrix. With a drop tolerance, garbage collection happens to be avoided + * for this matrix. During garbage collection, both internal and external + * fragmentation in the memory space is removed. Peak memory usage includes + * all internal memory fragmentation, even though this can be removed via + * garbage collection. + * + * Control parameters can also be set in the optional tmp/control.umf4 file. + * The right-hand-side can be provided in the optional tmp/b file. The solution + * is written to tmp/x, and the output statistics are written to tmp/info.umf4. + * + * After the matrix is factorized, solved, and the LU factors deallocated, + * this program then test the AMD ordering routine. This call to AMD is NOT + * part of the UMFPACK analysis, factorize, or solve steps. It is just a + * separate test of the AMD ordering routine. If the matrix is unsymmetric, + * AMD orders the pattern of A+A'. + */ + +#include +#include +#include +#include "umfpack.h" +#include "amd.h" + +#define SMAX 256 +#define ABS(x) ((x) >= 0 ? (x) : -(x)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +#define XTRUE(i,n) (1.0 + ((double) i) / ((double) n)) + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* -------------------------------------------------------------------------- */ +/* err: compute the relative error, ||x-xtrue||/||xtrue|| */ +/* -------------------------------------------------------------------------- */ + +static double err +( + int n, + double x [ ] +) +{ + int i ; + double enorm, e, abse, absxtrue, xnorm ; + enorm = 0 ; + xnorm = 0 ; + + for (i = 0 ; i < n ; i++) + { + if (isnan (x [i])) + { + enorm = x [i] ; + break ; + } + e = x [i] - XTRUE (i,n) ; + abse = ABS (e) ; + enorm = MAX (enorm, abse) ; + } + + for (i = 0 ; i < n ; i++) + { + /* XTRUE is positive, but do this in case XTRUE is redefined */ + absxtrue = ABS (XTRUE (i,n)) ; + xnorm = MAX (xnorm, absxtrue) ; + } + + if (xnorm == 0) + { + xnorm = 1 ; + } + return (enorm / xnorm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the relative residual, ||Ax-b||/||b|| or ||A'x-b||/||b|| */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + int n, + int Ap [ ], + int Ai [ ], + double Ax [ ], + double x [ ], + double r [ ], + double b [ ], + int transpose +) +{ + int i, j, p ; + double rnorm, absr, absb, bnorm ; + for (i = 0 ; i < n ; i++) + { + r [i] = 0 ; + } + + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [j] += Ax [p] * x [i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + } + } + } + + for (i = 0 ; i < n ; i++) + { + r [i] -= b [i] ; + } + rnorm = 0. ; + bnorm = 0. ; + for (i = 0 ; i < n ; i++) + { + if (isnan (r [i])) + { + rnorm = r [i] ; + break ; + } + absr = ABS (r [i]) ; + rnorm = MAX (rnorm, absr) ; + } + for (i = 0 ; i < n ; i++) + { + if (isnan (b [i])) + { + bnorm = b [i] ; + break ; + } + absb = ABS (b [i]) ; + bnorm = MAX (bnorm, absb) ; + } + if (bnorm == 0) + { + bnorm = 1 ; + } + return (rnorm / bnorm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* Atimesx: compute y = A*x or A'*x, where x (i) = 1 + i/n */ +/* -------------------------------------------------------------------------- */ + +static void Atimesx +( + int n, + int Ap [ ], + int Ai [ ], + double Ax [ ], + double y [ ], + int transpose +) +{ + int i, j, p ; + for (i = 0 ; i < n ; i++) + { + y [i] = 0 ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + y [j] += Ax [p] * XTRUE (i,n) ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + y [i] += Ax [p] * XTRUE (j,n) ; + } + } + } +} + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + int i, j, k, n, nz, *Ap, *Ai, *Ti, *Tj, status, *Pamd, nrow, ncol, rhs ; + double *Ax, *b, *x, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], aij, + *Tx, *r, amd_Control [AMD_CONTROL], amd_Info [AMD_INFO], tamd [2], + stats [2], droptol ; + void *Symbolic, *Numeric ; + FILE *f, *f2 ; + char s [SMAX] ; + + /* ---------------------------------------------------------------------- */ + /* set controls */ + /* ---------------------------------------------------------------------- */ + + printf ("\n===========================================================\n" + "=== UMFPACK v4.4 ==========================================\n" + "===========================================================\n") ; + + umfpack_di_defaults (Control) ; + Control [UMFPACK_PRL] = 3 ; + Control [UMFPACK_BLOCK_SIZE] = 32 ; + + f = fopen ("tmp/control.umf4", "r") ; + if (f != (FILE *) NULL) + { + printf ("Reading control file tmp/control.umf4\n") ; + for (i = 0 ; i < UMFPACK_CONTROL ; i++) + { + fscanf (f, "%lg\n", & Control [i]) ; + } + fclose (f) ; + } + + if (argc > 1) + { + char *s = argv [1] ; + + /* get the strategy */ + if (s [0] == 'u') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ; + } + else if (s [0] == 'a') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ; + } + else if (s [0] == 's') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ; + } + else if (s [0] == '2') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2 ; + } + else if (s [0] == 'U') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ; + Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; + } + else if (s [0] == 'A') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ; + Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; + } + else if (s [0] == 'S') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ; + Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; + } + else if (s [0] == 'T') + { + Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2 ; + Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ; + } + else + { + printf ("unrecognized strategy: %s\n", argv [1]) ; + } + + if (s [1] == 'n') + { + /* no aggressive absorption */ + Control [UMFPACK_AGGRESSIVE] = FALSE ; + } + } + + if (argc > 2) + { + /* get the drop tolerance */ + sscanf (argv [2], "%lg", &droptol) ; + printf ("droptol %g\n", droptol) ; + Control [UMFPACK_DROPTOL] = droptol ; + } + + umfpack_di_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* open the matrix file (tmp/A) */ + /* ---------------------------------------------------------------------- */ + + printf ("File: tmp/A\n") ; + f = fopen ("tmp/A", "r") ; + if (!f) + { + printf ("Unable to open file\n") ; + exit (1) ; + } + + /* ---------------------------------------------------------------------- */ + /* get n and nz */ + /* ---------------------------------------------------------------------- */ + + printf ("File: tmp/Asize\n") ; + f2 = fopen ("tmp/Asize", "r") ; + if (f2) + { + fscanf (f2, "%d %d %d\n", &nrow, &ncol, &nz) ; + fclose (f2) ; + } + else + { + nrow = 1 ; + ncol = 1 ; + } + nz = 0 ; + while (fgets (s, SMAX, f) != (char *) NULL) + { + sscanf (s, "%d %d %lg", &i, &j, &aij) ; +#ifdef ZERO_BASED + /* matrix is zero based */ + i++ ; + j++ ; +#endif + nrow = MAX (nrow, i) ; + ncol = MAX (ncol, j) ; + nz++ ; + } + fclose (f) ; + n = MAX (nrow, ncol) ; + + printf ("n %d nrow %d ncol %d nz %d\n", n, nrow, ncol, nz) ; + + /* ---------------------------------------------------------------------- */ + /* allocate space for the input triplet form */ + /* ---------------------------------------------------------------------- */ + + Ti = (int *) malloc (nz * sizeof (int)) ; + Tj = (int *) malloc (nz * sizeof (int)) ; + Tx = (double *) malloc (nz * sizeof (double)) ; + if (!Ti || !Tj || !Tx) + { + printf ("out of memory for input matrix\n") ; + exit (1) ; + } + + /* ---------------------------------------------------------------------- */ + /* read in the triplet form */ + /* ---------------------------------------------------------------------- */ + + f2 = fopen ("tmp/A", "r") ; + if (!f2) + { + printf ("Unable to open file\n") ; + exit (1) ; + } + + k = 0 ; + while (fgets (s, SMAX, f2) != (char *) NULL) + { + sscanf (s, "%d %d %lg", &i, &j, &aij) ; +#ifndef ZERO_BASED + i-- ; /* convert to 0-based */ + j-- ; +#endif + if (k >= nz) + { + printf ("Error! Matrix size is wrong\n") ; + exit (1) ; + } + Ti [k] = i ; + Tj [k] = j ; + Tx [k] = aij ; + k++ ; + } + fclose (f2) ; + + (void) umfpack_di_report_triplet (nrow, ncol, nz, Ti, Tj, Tx, Control) ; + + /* ---------------------------------------------------------------------- */ + /* convert to column form */ + /* ---------------------------------------------------------------------- */ + + /* convert to column form */ + Ap = (int *) malloc ((n+1) * sizeof (int)) ; + Ai = (int *) malloc (nz * sizeof (int)) ; + Ax = (double *) malloc (nz * sizeof (double)) ; + b = (double *) malloc (n * sizeof (double)) ; + r = (double *) malloc (n * sizeof (double)) ; + x = (double *) malloc (n * sizeof (double)) ; + if (!Ap || !Ai || !Ax || !b || !r) + { + printf ("out of memory") ; + exit (1) ; + } + umfpack_tic (stats) ; + status = umfpack_di_triplet_to_col (nrow, ncol, nz, Ti, Tj, Tx, Ap, Ai, Ax, + (int *) NULL) ; + umfpack_toc (stats) ; + printf ("triplet-to-col time: wall %g cpu %g\n", stats [0], stats [1]) ; + if (status != UMFPACK_OK) + { + umfpack_di_report_status (Control, status) ; + printf ("umfpack_di_triplet_to_col failed") ; + exit (1) ; + } + + /* print the column-form of A */ + (void) umfpack_di_report_matrix (nrow, ncol, Ap, Ai, Ax, 1, Control) ; + + /* b = A * xtrue */ + rhs = FALSE ; + if (nrow == ncol) + { + f = fopen ("tmp/b", "r") ; + if (f != (FILE *) NULL) + { + printf ("Reading tmp/b\n") ; + rhs = TRUE ; + for (i = 0 ; i < n ; i++) + { + fscanf (f, "%lg\n", &b [i]) ; + } + fclose (f) ; + } + else + { + Atimesx (n, Ap, Ai, Ax, b, FALSE) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* free the triplet form */ + /* ---------------------------------------------------------------------- */ + + free (Ti) ; + free (Tj) ; + free (Tx) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_symbolic (nrow, ncol, Ap, Ai, Ax, &Symbolic, + Control, Info) ; + + umfpack_di_report_info (Control, Info) ; + if (status != UMFPACK_OK) + { + umfpack_di_report_status (Control, status) ; + printf ("umfpack_di_symbolic failed") ; + exit (1) ; + } + + /* print the symbolic factorization */ + (void) umfpack_di_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info); + if (status < UMFPACK_OK) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + fprintf (stderr, "umfpack_di_numeric failed: %d\n", status) ; + printf ("umfpack_di_numeric failed\n") ; + exit (1) ; + } + + /* print the numeric factorization */ + (void) umfpack_di_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + if (nrow == ncol && status == UMFPACK_OK) + { + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, + Control, Info) ; + + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + if (status < UMFPACK_OK) + { + printf ("umfpack_di_solve failed\n") ; + exit (1) ; + } + (void) umfpack_di_report_vector (n, x, Control) ; + printf ("relative maxnorm of residual, ||Ax-b||/||b||: %g\n", + resid (n, Ap, Ai, Ax, x, r, b, FALSE)) ; + if (!rhs) + { + printf ("relative maxnorm of error, ||x-xtrue||/||xtrue||: %g\n\n", + err (n, x)) ; + } + + f = fopen ("tmp/x", "w") ; + if (f != (FILE *) NULL) + { + printf ("Writing tmp/x\n") ; + for (i = 0 ; i < n ; i++) + { + fprintf (f, "%30.20e\n", x [i]) ; + } + fclose (f) ; + } + else + { + printf ("Unable to write output x!\n") ; + exit (1) ; + } + + f = fopen ("tmp/info.umf4", "w") ; + if (f != (FILE *) NULL) + { + printf ("Writing tmp/info.umf4\n") ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + fprintf (f, "%30.20e\n", Info [i]) ; + } + fclose (f) ; + } + else + { + printf ("Unable to write output info!\n") ; + exit (1) ; + } + } + else + { + /* don't solve, just report the results */ + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + } + + /* ---------------------------------------------------------------------- */ + /* free the Symbolic and Numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_di_free_symbolic (&Symbolic) ; + umfpack_di_free_numeric (&Numeric) ; + + printf ("umf4 done, strategy: %g\n", Control [UMFPACK_STRATEGY]) ; + + /* ---------------------------------------------------------------------- */ + /* test just AMD ordering (not part of UMFPACK, but a separate test) */ + /* ---------------------------------------------------------------------- */ + + /* first make the matrix square */ + if (ncol < n) + { + for (j = ncol+1 ; j <= n ; j++) + { + Ap [j] = Ap [ncol] ; + } + } + + printf ( + "\n\n===========================================================\n" + "=== AMD ===================================================\n" + "===========================================================\n") ; + printf ("\n\n------- Now trying the AMD ordering. This not part of\n" + "the UMFPACK analysis or factorization, above, but a separate\n" + "test of just the AMD ordering routine.\n") ; + Pamd = (int *) malloc (n * sizeof (int)) ; + if (!Pamd) + { + printf ("out of memory\n") ; + exit (1) ; + } + amd_defaults (amd_Control) ; + amd_control (amd_Control) ; + umfpack_tic (tamd) ; + status = amd_order (n, Ap, Ai, Pamd, amd_Control, amd_Info) ; + umfpack_toc (tamd) ; + printf ("AMD ordering time: cpu %10.2f wall %10.2f\n", + tamd [1], tamd [0]) ; + if (status != AMD_OK) + { + printf ("amd failed: %d\n", status) ; + exit (1) ; + } + amd_info (amd_Info) ; + free (Pamd) ; + printf ("AMD test done\n") ; + + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4.out b/liboctave/UMFPACK/UMFPACK/Demo/umf4.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4.out @@ -0,0 +1,1970 @@ +cc -O -DNBLAS -I../Include -I../../AMD/Include -o umf4 umf4.c ../Lib/libumfpack.a ../../AMD/Lib/libamd.a -lm +f77 -O -o readhb readhb.f +f77 -O -o readhb_nozeros readhb_nozeros.f +f77 -O -o readhb_size readhb_size.f +./readhb_nozeros < HB/can_24.psa > tmp/A +Matrix key: CAN 24 +./readhb_size < HB/can_24.psa > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 24 nrow 24 ncol 24 nz 160 +triplet-form matrix, n_row = 24, n_col = 24 nz = 160. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 24 n_col 24, nz = 160. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 24 + number of columns in matrix A: 24 + entries in matrix A: 160 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 0 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 24 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 136 + nz on diagonal of matrix S: 24 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.00300e+03 + est. nz in L+U (incl. diagonal): 218 + est. largest front (# entries): 64 + est. max nz in any column of L: 8 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 718 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 124 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 739 - - + peak size (Units) 3244 - - + final size (Units) 393 - - + Numeric final size (Units) 591 - - + Numeric final size (MBytes) 0.0 - - + peak memory usage (Units) 3826 - - + peak memory usage (MBytes) 0.0 - - + numeric factorization flops 2.37900e+03 - - + nz in L (incl diagonal) 149 - - + nz in U (incl diagonal) 208 - - + nz in L+U (incl diagonal) 333 - - + largest front (# entries) 182 - - + largest # rows in front 13 - - + largest # columns in front 14 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 24 + number of columns in matrix A: 24 + entries in matrix A: 160 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 0 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 24 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 136 + nz on diagonal of matrix S: 24 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.00300e+03 + est. nz in L+U (incl. diagonal): 218 + est. largest front (# entries): 64 + est. max nz in any column of L: 8 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 718 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 124 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 9.00000e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 739 712 96% + peak size (Units) 3244 2712 84% + final size (Units) 393 179 46% + Numeric final size (Units) 591 365 62% + Numeric final size (MBytes) 0.0 0.0 62% + peak memory usage (Units) 3826 3294 86% + peak memory usage (MBytes) 0.0 0.0 86% + numeric factorization flops 2.37900e+03 3.32000e+02 14% + nz in L (incl diagonal) 149 78 52% + nz in U (incl diagonal) 208 86 41% + nz in L+U (incl diagonal) 333 140 42% + largest front (# entries) 182 78 43% + largest # rows in front 13 7 54% + largest # columns in front 14 13 93% + + initial allocation ratio used: 1.2 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 10 + nz in L (incl diagonal), if none dropped 78 + nz in U (incl diagonal), if none dropped 86 + number of small entries dropped 0 + nonzeros on diagonal of U: 24 + min abs. value on diagonal of U: 1.11e-01 + max abs. value on diagonal of U: 2.50e-01 + estimate of reciprocal of condition number: 4.44e-01 + indices in compressed pattern: 92 + numerical values stored in Numeric object: 140 + numeric factorization defragmentations: 0 + numeric factorization reallocations: 0 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.13600e+03 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 1.22e-16 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.46800e+03 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 24. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.2919e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.1716e-15 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 24 + nz, number of nonzeros in A: 160 + symmetry of A: 1.0000 + number of nonzeros on diagonal: 24 + nonzeros in pattern of A+A' (excl. diagonal): 136 + # dense rows/columns of A+A': 0 + memory used, in bytes: 1516 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 97 + nonzeros in L (including diagonal): 121 + # divide operations for LDL' or LU: 97 + # multiply-subtract operations for LDL': 275 + # multiply-subtract operations for LU: 453 + max nz. in any column of L (incl. diagonal): 8 + + chol flop count for real A, sqrt counted as 1 flop: 671 + LDL' flop count for real A: 647 + LDL' flop count for complex A: 3073 + LU flop count for real A (with no pivoting): 1003 + LU flop count for complex A (with no pivoting): 4497 + +AMD test done +./readhb_nozeros < HB/west0067.rua > tmp/A +Matrix key: WEST0067 +./readhb_size < HB/west0067.rua > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 67 nrow 67 ncol 67 nz 294 +triplet-form matrix, n_row = 67, n_col = 67 nz = 294. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 67 n_col 67, nz = 294. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 67 + number of columns in matrix A: 67 + entries in matrix A: 294 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 1 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S not square or diagonal not preserved + symbolic factorization defragmentations: 1 + symbolic memory usage (Units): 1632 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 245 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 1643 - - + peak size (Units) 6115 - - + final size (Units) 1628 - - + Numeric final size (Units) 2101 - - + Numeric final size (MBytes) 0.0 - - + peak memory usage (Units) 7462 - - + peak memory usage (MBytes) 0.1 - - + numeric factorization flops 1.41920e+04 - - + nz in L (incl diagonal) 542 - - + nz in U (incl diagonal) 902 - - + nz in L+U (incl diagonal) 1377 - - + largest front (# entries) 483 - - + largest # rows in front 21 - - + largest # columns in front 23 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 67 + number of columns in matrix A: 67 + entries in matrix A: 294 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 1 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S not square or diagonal not preserved + symbolic factorization defragmentations: 1 + symbolic memory usage (Units): 1632 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 245 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.01 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 6.59006e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 1643 1574 96% + peak size (Units) 6115 3581 59% + final size (Units) 1628 685 42% + Numeric final size (Units) 2101 1125 54% + Numeric final size (MBytes) 0.0 0.0 54% + peak memory usage (Units) 7462 4928 66% + peak memory usage (MBytes) 0.1 0.0 66% + numeric factorization flops 1.41920e+04 2.58700e+03 18% + nz in L (incl diagonal) 542 329 61% + nz in U (incl diagonal) 902 340 38% + nz in L+U (incl diagonal) 1377 602 44% + largest front (# entries) 483 80 17% + largest # rows in front 21 10 48% + largest # columns in front 23 11 48% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 329 + nz in U (incl diagonal), if none dropped 340 + number of small entries dropped 0 + nonzeros on diagonal of U: 67 + min abs. value on diagonal of U: 2.74e-02 + max abs. value on diagonal of U: 2.28e+00 + estimate of reciprocal of condition number: 1.20e-02 + indices in compressed pattern: 256 + numerical values stored in Numeric object: 605 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.01 + symbolic + numeric mflops (wall clock): 0.26 + + solve flops: 6.19300e+03 + iterative refinement steps taken: 1 + iterative refinement steps attempted: 1 + sparse backward error omega1: 9.49e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 8.78000e+03 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.01 + total symbolic+numeric+solve mflops(wallclock) 0.88 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 67. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.83101e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 2.47921e-15 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 67 + nz, number of nonzeros in A: 294 + symmetry of A: 0.0342 + number of nonzeros on diagonal: 2 + nonzeros in pattern of A+A' (excl. diagonal): 574 + # dense rows/columns of A+A': 0 + memory used, in bytes: 5164 + # of memory compactions: 1 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 930 + nonzeros in L (including diagonal): 997 + # divide operations for LDL' or LU: 930 + # multiply-subtract operations for LDL': 9170 + # multiply-subtract operations for LU: 17410 + max nz. in any column of L (incl. diagonal): 33 + + chol flop count for real A, sqrt counted as 1 flop: 19337 + LDL' flop count for real A: 19270 + LDL' flop count for complex A: 81730 + LU flop count for real A (with no pivoting): 35750 + LU flop count for complex A (with no pivoting): 147650 + +AMD test done +./readhb_nozeros < HB/fs_183_6.rua > tmp/A +Matrix key: FS 183 6 +./readhb_size < HB/fs_183_6.rua > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 183 nrow 183 ncol 183 nz 1000 +triplet-form matrix, n_row = 183, n_col = 183 nz = 1000. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 183 n_col 183, nz = 1000. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 183 + number of columns in matrix A: 183 + entries in matrix A: 1000 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric 2-by-2 + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 36 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 4 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 147 + symmetry of nonzero pattern: 0.490515 + nz in S+S' (excl. diagonal): 1114 + nz on diagonal of matrix S: 147 + fraction of nz on diagonal: 1.000000 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 7 + # unmatched: 7 + symmetry of P2*S: 0.490515 + nz in P2*S+(P2*S)' (excl. diag.): 1114 + nz on diagonal of P2*S: 147 + fraction of nz on diag of P2*S: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.02930e+04 + est. nz in L+U (incl. diagonal): 1625 + est. largest front (# entries): 196 + est. max nz in any column of L: 14 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4839 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 756 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4274 - - + peak size (Units) 26277 - - + final size (Units) 15717 - - + Numeric final size (Units) 16944 - - + Numeric final size (MBytes) 0.1 - - + peak memory usage (Units) 29673 - - + peak memory usage (MBytes) 0.2 - - + numeric factorization flops 2.67903e+05 - - + nz in L (incl diagonal) 2122 - - + nz in U (incl diagonal) 9931 - - + nz in L+U (incl diagonal) 11870 - - + largest front (# entries) 2337 - - + largest # rows in front 21 - - + largest # columns in front 136 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 183 + number of columns in matrix A: 183 + entries in matrix A: 1000 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric 2-by-2 + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 36 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 4 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 147 + symmetry of nonzero pattern: 0.490515 + nz in S+S' (excl. diagonal): 1114 + nz on diagonal of matrix S: 147 + fraction of nz on diagonal: 1.000000 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 7 + # unmatched: 7 + symmetry of P2*S: 0.490515 + nz in P2*S+(P2*S)' (excl. diag.): 1114 + nz on diagonal of P2*S: 147 + fraction of nz on diag of P2*S: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.02930e+04 + est. nz in L+U (incl. diagonal): 1625 + est. largest front (# entries): 196 + est. max nz in any column of L: 14 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4839 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 756 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.84689e-01 + maximum sum (abs (rows of A)): 8.73139e+08 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4274 4089 96% + peak size (Units) 26277 8291 32% + final size (Units) 15717 1658 11% + Numeric final size (Units) 16944 2794 16% + Numeric final size (MBytes) 0.1 0.0 16% + peak memory usage (Units) 29673 11687 39% + peak memory usage (MBytes) 0.2 0.1 39% + numeric factorization flops 2.67903e+05 7.82700e+03 3% + nz in L (incl diagonal) 2122 838 39% + nz in U (incl diagonal) 9931 804 8% + nz in L+U (incl diagonal) 11870 1459 12% + largest front (# entries) 2337 420 18% + largest # rows in front 21 14 67% + largest # columns in front 136 36 26% + + initial allocation ratio used: 0.265 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 3 + nz in L (incl diagonal), if none dropped 838 + nz in U (incl diagonal), if none dropped 804 + number of small entries dropped 0 + nonzeros on diagonal of U: 183 + min abs. value on diagonal of U: 2.30e-09 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.30e-09 + indices in compressed pattern: 550 + numerical values stored in Numeric object: 1396 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.79470e+04 + iterative refinement steps taken: 1 + iterative refinement steps attempted: 1 + sparse backward error omega1: 1.51e-16 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 2.57740e+04 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 183. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.55669e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.08984e-06 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 183 + nz, number of nonzeros in A: 1000 + symmetry of A: 0.4431 + number of nonzeros on diagonal: 183 + nonzeros in pattern of A+A' (excl. diagonal): 1272 + # dense rows/columns of A+A': 0 + memory used, in bytes: 12692 + # of memory compactions: 1 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 882 + nonzeros in L (including diagonal): 1065 + # divide operations for LDL' or LU: 882 + # multiply-subtract operations for LDL': 3378 + # multiply-subtract operations for LU: 5874 + max nz. in any column of L (incl. diagonal): 15 + + chol flop count for real A, sqrt counted as 1 flop: 7821 + LDL' flop count for real A: 7638 + LDL' flop count for complex A: 34962 + LU flop count for real A (with no pivoting): 12630 + LU flop count for complex A (with no pivoting): 54930 + +AMD test done +./readhb < HB/fs_183_6.rua > tmp/A +Matrix key: FS 183 6 +./readhb_size < HB/fs_183_6.rua > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 183 nrow 183 ncol 183 nz 1069 +triplet-form matrix, n_row = 183, n_col = 183 nz = 1069. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 183 n_col 183, nz = 1069. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 183 + number of columns in matrix A: 183 + entries in matrix A: 1069 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric 2-by-2 + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 29 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 4 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 154 + symmetry of nonzero pattern: 0.446860 + nz in S+S' (excl. diagonal): 1286 + nz on diagonal of matrix S: 154 + fraction of nz on diagonal: 1.000000 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 7 + # unmatched: 7 + symmetry of P2*S: 0.446860 + nz in P2*S+(P2*S)' (excl. diag.): 1286 + nz on diagonal of P2*S: 154 + fraction of nz on diag of P2*S: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.78450e+04 + est. nz in L+U (incl. diagonal): 2080 + est. largest front (# entries): 400 + est. max nz in any column of L: 20 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4959 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 766 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4558 - - + peak size (Units) 26357 - - + final size (Units) 17822 - - + Numeric final size (Units) 19049 - - + Numeric final size (MBytes) 0.1 - - + peak memory usage (Units) 29795 - - + peak memory usage (MBytes) 0.2 - - + numeric factorization flops 3.51312e+05 - - + nz in L (incl diagonal) 2633 - - + nz in U (incl diagonal) 10968 - - + nz in L+U (incl diagonal) 13418 - - + largest front (# entries) 3220 - - + largest # rows in front 25 - - + largest # columns in front 140 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 183 + number of columns in matrix A: 183 + entries in matrix A: 1069 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric 2-by-2 + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 29 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 4 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 154 + symmetry of nonzero pattern: 0.446860 + nz in S+S' (excl. diagonal): 1286 + nz on diagonal of matrix S: 154 + fraction of nz on diagonal: 1.000000 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 7 + # unmatched: 7 + symmetry of P2*S: 0.446860 + nz in P2*S+(P2*S)' (excl. diag.): 1286 + nz on diagonal of P2*S: 154 + fraction of nz on diag of P2*S: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.78450e+04 + est. nz in L+U (incl. diagonal): 2080 + est. largest front (# entries): 400 + est. max nz in any column of L: 20 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4959 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 766 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.84689e-01 + maximum sum (abs (rows of A)): 8.73139e+08 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4558 4376 96% + peak size (Units) 26357 11140 42% + final size (Units) 17822 2107 12% + Numeric final size (Units) 19049 3243 17% + Numeric final size (MBytes) 0.1 0.0 17% + peak memory usage (Units) 29795 14578 49% + peak memory usage (MBytes) 0.2 0.1 49% + numeric factorization flops 3.51312e+05 1.19670e+04 3% + nz in L (incl diagonal) 2633 1136 43% + nz in U (incl diagonal) 10968 870 8% + nz in L+U (incl diagonal) 13418 1823 14% + largest front (# entries) 3220 728 23% + largest # rows in front 25 20 80% + largest # columns in front 140 58 41% + + initial allocation ratio used: 0.282 + # of forced updates due to frontal growth: 2 + number of off-diagonal pivots: 3 + nz in L (incl diagonal), if none dropped 1136 + nz in U (incl diagonal), if none dropped 870 + number of small entries dropped 0 + nonzeros on diagonal of U: 183 + min abs. value on diagonal of U: 2.30e-09 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.30e-09 + indices in compressed pattern: 741 + numerical values stored in Numeric object: 1781 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 1 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 2.00240e+04 + iterative refinement steps taken: 1 + iterative refinement steps attempted: 1 + sparse backward error omega1: 2.21e-16 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 3.19910e+04 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 183. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.94586e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.22537e-06 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.01 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 183 + nz, number of nonzeros in A: 1069 + symmetry of A: 0.4176 + number of nonzeros on diagonal: 183 + nonzeros in pattern of A+A' (excl. diagonal): 1402 + # dense rows/columns of A+A': 0 + memory used, in bytes: 13316 + # of memory compactions: 1 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 1072 + nonzeros in L (including diagonal): 1255 + # divide operations for LDL' or LU: 1072 + # multiply-subtract operations for LDL': 5320 + # multiply-subtract operations for LU: 9568 + max nz. in any column of L (incl. diagonal): 21 + + chol flop count for real A, sqrt counted as 1 flop: 11895 + LDL' flop count for real A: 11712 + LDL' flop count for complex A: 52208 + LU flop count for real A (with no pivoting): 20208 + LU flop count for complex A (with no pivoting): 86192 + +AMD test done +./readhb < HB/arc130.rua > tmp/A +Matrix key: ARC130 +./readhb_size < HB/arc130.rua > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 130 nrow 130 ncol 130 nz 1282 +triplet-form matrix, n_row = 130, n_col = 130 nz = 1282. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 130 n_col 130, nz = 1282. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1282 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 6 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 7 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 124 + symmetry of nonzero pattern: 0.841193 + nz in S+S' (excl. diagonal): 1204 + nz on diagonal of matrix S: 124 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 8.27000e+03 + est. nz in L+U (incl. diagonal): 1336 + est. largest front (# entries): 324 + est. max nz in any column of L: 18 + number of "dense" rows/columns in S+S': 2 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4759 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 637 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4599 - - + peak size (Units) 25036 - - + final size (Units) 12837 - - + Numeric final size (Units) 13724 - - + Numeric final size (MBytes) 0.1 - - + peak memory usage (Units) 27681 - - + peak memory usage (MBytes) 0.2 - - + numeric factorization flops 9.41610e+04 - - + nz in L (incl diagonal) 1009 - - + nz in U (incl diagonal) 7849 - - + nz in L+U (incl diagonal) 8728 - - + largest front (# entries) 2337 - - + largest # rows in front 19 - - + largest # columns in front 123 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1282 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 6 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 7 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 124 + symmetry of nonzero pattern: 0.841193 + nz in S+S' (excl. diagonal): 1204 + nz on diagonal of matrix S: 124 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 8.27000e+03 + est. nz in L+U (incl. diagonal): 1336 + est. largest front (# entries): 324 + est. max nz in any column of L: 18 + number of "dense" rows/columns in S+S': 2 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4759 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 637 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 7.94859e-01 + maximum sum (abs (rows of A)): 1.08460e+06 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 4599 4452 97% + peak size (Units) 25036 6478 26% + final size (Units) 12837 1054 8% + Numeric final size (Units) 13724 1876 14% + Numeric final size (MBytes) 0.1 0.0 14% + peak memory usage (Units) 27681 9123 33% + peak memory usage (MBytes) 0.2 0.1 33% + numeric factorization flops 9.41610e+04 4.20900e+03 4% + nz in L (incl diagonal) 1009 417 41% + nz in U (incl diagonal) 7849 787 10% + nz in L+U (incl diagonal) 8728 1074 12% + largest front (# entries) 2337 270 12% + largest # rows in front 19 18 95% + largest # columns in front 123 15 12% + + initial allocation ratio used: 0.36 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 0 + nz in L (incl diagonal), if none dropped 417 + nz in U (incl diagonal), if none dropped 796 + number of small entries dropped 9 + nonzeros on diagonal of U: 130 + min abs. value on diagonal of U: 9.22e-07 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 9.22e-07 + indices in compressed pattern: 79 + numerical values stored in Numeric object: 977 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.80440e+04 + iterative refinement steps taken: 1 + iterative refinement steps attempted: 1 + sparse backward error omega1: 8.47e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 2.22530e+04 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 130. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.37368e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.74277e-10 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 130 + nz, number of nonzeros in A: 1282 + symmetry of A: 0.7587 + number of nonzeros on diagonal: 130 + nonzeros in pattern of A+A' (excl. diagonal): 1430 + # dense rows/columns of A+A': 2 + memory used, in bytes: 11544 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 756 + nonzeros in L (including diagonal): 886 + # divide operations for LDL' or LU: 756 + # multiply-subtract operations for LDL': 2959 + # multiply-subtract operations for LU: 5162 + max nz. in any column of L (incl. diagonal): 18 + + chol flop count for real A, sqrt counted as 1 flop: 6804 + LDL' flop count for real A: 6674 + LDL' flop count for complex A: 30476 + LU flop count for real A (with no pivoting): 11080 + LU flop count for complex A (with no pivoting): 48100 + +AMD test done +./readhb_nozeros < HB/arc130.rua > tmp/A +Matrix key: ARC130 +./readhb_size < HB/arc130.rua > tmp/Asize +./umf4 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 130 nrow 130 ncol 130 nz 1037 +triplet-form matrix, n_row = 130, n_col = 130 nz = 1037. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 130 n_col 130, nz = 1037. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1037 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 54 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 5 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 76 + symmetry of nonzero pattern: 0.733224 + nz in S+S' (excl. diagonal): 774 + nz on diagonal of matrix S: 76 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 5.81700e+03 + est. nz in L+U (incl. diagonal): 858 + est. largest front (# entries): 289 + est. max nz in any column of L: 17 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4111 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 527 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 3196 - - + peak size (Units) 9801 - - + final size (Units) 4259 - - + Numeric final size (Units) 5146 - - + Numeric final size (MBytes) 0.0 - - + peak memory usage (Units) 12135 - - + peak memory usage (MBytes) 0.1 - - + numeric factorization flops 2.47640e+04 - - + nz in L (incl diagonal) 606 - - + nz in U (incl diagonal) 2537 - - + nz in L+U (incl diagonal) 3013 - - + largest front (# entries) 459 - - + largest # rows in front 17 - - + largest # columns in front 48 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1037 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 54 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 5 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 76 + symmetry of nonzero pattern: 0.733224 + nz in S+S' (excl. diagonal): 774 + nz on diagonal of matrix S: 76 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 5.81700e+03 + est. nz in L+U (incl. diagonal): 858 + est. largest front (# entries): 289 + est. max nz in any column of L: 17 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4111 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 527 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 7.94859e-01 + maximum sum (abs (rows of A)): 1.08460e+06 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 3196 3062 96% + peak size (Units) 9801 6376 65% + final size (Units) 4259 1141 27% + Numeric final size (Units) 5146 1963 38% + Numeric final size (MBytes) 0.0 0.0 38% + peak memory usage (Units) 12135 8710 72% + peak memory usage (MBytes) 0.1 0.1 72% + numeric factorization flops 2.47640e+04 4.10700e+03 17% + nz in L (incl diagonal) 606 409 67% + nz in U (incl diagonal) 2537 792 31% + nz in L+U (incl diagonal) 3013 1071 36% + largest front (# entries) 459 240 52% + largest # rows in front 17 16 94% + largest # columns in front 48 15 31% + + initial allocation ratio used: 0.755 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 0 + nz in L (incl diagonal), if none dropped 409 + nz in U (incl diagonal), if none dropped 792 + number of small entries dropped 0 + nonzeros on diagonal of U: 130 + min abs. value on diagonal of U: 9.22e-07 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 9.22e-07 + indices in compressed pattern: 70 + numerical values stored in Numeric object: 782 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.58270e+04 + iterative refinement steps taken: 1 + iterative refinement steps attempted: 1 + sparse backward error omega1: 7.18e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.99340e+04 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 130. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.37368e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.74255e-10 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 130 + nz, number of nonzeros in A: 1037 + symmetry of A: 0.4939 + number of nonzeros on diagonal: 130 + nonzeros in pattern of A+A' (excl. diagonal): 1366 + # dense rows/columns of A+A': 2 + memory used, in bytes: 11236 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 725 + nonzeros in L (including diagonal): 855 + # divide operations for LDL' or LU: 725 + # multiply-subtract operations for LDL': 2742 + # multiply-subtract operations for LU: 4759 + max nz. in any column of L (incl. diagonal): 18 + + chol flop count for real A, sqrt counted as 1 flop: 6339 + LDL' flop count for real A: 6209 + LDL' flop count for complex A: 28461 + LU flop count for real A (with no pivoting): 10243 + LU flop count for complex A (with no pivoting): 44597 + +AMD test done +./readhb_nozeros < HB/arc130.rua > tmp/A +Matrix key: ARC130 +./readhb_size < HB/arc130.rua > tmp/Asize +./umf4 a 1e-6 + +=========================================================== +=== UMFPACK v4.4 ========================================== +=========================================================== +droptol 1e-06 + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 3 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 1e-06 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +File: tmp/A +File: tmp/Asize +n 130 nrow 130 ncol 130 nz 1037 +triplet-form matrix, n_row = 130, n_col = 130 nz = 1037. OK + +triplet-to-col time: wall 0 cpu 0 +column-form matrix, n_row 130 n_col 130, nz = 1037. OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1037 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 54 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 5 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 76 + symmetry of nonzero pattern: 0.733224 + nz in S+S' (excl. diagonal): 774 + nz on diagonal of matrix S: 76 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 5.81700e+03 + est. nz in L+U (incl. diagonal): 858 + est. largest front (# entries): 289 + est. max nz in any column of L: 17 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4111 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 527 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 3196 - - + peak size (Units) 9801 - - + final size (Units) 4259 - - + Numeric final size (Units) 5146 - - + Numeric final size (MBytes) 0.0 - - + peak memory usage (Units) 12135 - - + peak memory usage (MBytes) 0.1 - - + numeric factorization flops 2.47640e+04 - - + nz in L (incl diagonal) 606 - - + nz in U (incl diagonal) 2537 - - + nz in L+U (incl diagonal) 3013 - - + largest front (# entries) 459 - - + largest # rows in front 17 - - + largest # columns in front 48 - - + +Symbolic object: OK + +Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 130 + number of columns in matrix A: 130 + entries in matrix A: 1037 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 54 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 5 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 76 + symmetry of nonzero pattern: 0.733224 + nz in S+S' (excl. diagonal): 774 + nz on diagonal of matrix S: 76 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 5.81700e+03 + est. nz in L+U (incl. diagonal): 858 + est. largest front (# entries): 289 + est. max nz in any column of L: 17 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 4111 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 527 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 7.94859e-01 + maximum sum (abs (rows of A)): 1.08460e+06 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 3196 2762 86% + peak size (Units) 9801 5323 54% + final size (Units) 4259 457 11% + Numeric final size (Units) 5146 1279 25% + Numeric final size (MBytes) 0.0 0.0 25% + peak memory usage (Units) 12135 7657 63% + peak memory usage (MBytes) 0.1 0.1 63% + numeric factorization flops 2.47640e+04 4.10700e+03 17% + nz in L (incl diagonal) 606 318 52% + nz in U (incl diagonal) 2537 285 11% + nz in L+U (incl diagonal) 3013 473 16% + largest front (# entries) 459 240 52% + largest # rows in front 17 16 94% + largest # columns in front 48 15 31% + + initial allocation ratio used: 0.755 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 0 + nz in L (incl diagonal), if none dropped 409 + nz in U (incl diagonal), if none dropped 792 + number of small entries dropped 598 + nonzeros on diagonal of U: 130 + min abs. value on diagonal of U: 9.22e-07 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 9.22e-07 + indices in compressed pattern: 82 + numerical values stored in Numeric object: 386 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 2.06060e+04 + iterative refinement steps taken: 2 + iterative refinement steps attempted: 2 + sparse backward error omega1: 1.30e-16 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 2.47130e+04 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK V4.4 (Jan. 28, 2005): OK + +dense vector, n = 130. OK + +relative maxnorm of residual, ||Ax-b||/||b||: 1.37368e-16 +relative maxnorm of error, ||x-xtrue||/||xtrue||: 1.94084e-10 + +Writing tmp/x +Writing tmp/info.umf4 +umf4 done, strategy: 0 + + +=========================================================== +=== AMD =================================================== +=========================================================== + + +------- Now trying the AMD ordering. This not part of +the UMFPACK analysis or factorization, above, but a separate +test of just the AMD ordering routine. + +amd: approximate minimum degree ordering, parameters: + dense row parameter: 10 + (rows with more than max (10 * sqrt (n), 16) entries are + considered "dense", and placed last in output permutation) + aggressive absorption: yes + +AMD ordering time: cpu 0.00 wall 0.00 + +amd: approximate minimum degree ordering, results: + status: OK + n, dimension of A: 130 + nz, number of nonzeros in A: 1037 + symmetry of A: 0.4939 + number of nonzeros on diagonal: 130 + nonzeros in pattern of A+A' (excl. diagonal): 1366 + # dense rows/columns of A+A': 2 + memory used, in bytes: 11236 + # of memory compactions: 0 + + The following approximate statistics are for a subsequent + factorization of A(P,P) + A(P,P)'. They are slight upper + bounds if there are no dense rows/columns in A+A', and become + looser if dense rows/columns exist. + + nonzeros in L (excluding diagonal): 725 + nonzeros in L (including diagonal): 855 + # divide operations for LDL' or LU: 725 + # multiply-subtract operations for LDL': 2742 + # multiply-subtract operations for LU: 4759 + max nz. in any column of L (incl. diagonal): 18 + + chol flop count for real A, sqrt counted as 1 flop: 6339 + LDL' flop count for real A: 6209 + LDL' flop count for complex A: 28461 + LU flop count for real A (with no pivoting): 10243 + LU flop count for complex A (with no pivoting): 44597 + +AMD test done diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77wrapper.c b/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77wrapper.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77wrapper.c @@ -0,0 +1,505 @@ +/* ========================================================================== */ +/* === umf4_f77wrapper ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* FORTRAN interface for the C-callable UMFPACK library (double / int version + * only and double / long versions only). This is HIGHLY non-portable. You + * will need to modify this depending on how your FORTRAN and C compilers + * behave. This has been tested in Linux, Sun Solaris, SGI IRIX, and IBM AIX, + * with various compilers. It has not been exhaustively tested on all possible + * combinations of C and FORTRAN compilers. The long version works on + * Solaris, SGI IRIX, and IBM AIX when the UMFPACK library is compiled in + * 64-bit mode. + * + * Only a subset of UMFPACK's capabilities are provided. Refer to the UMFPACK + * User Guide for details. + * + * For some C and FORTRAN compilers, the FORTRAN compiler appends a single + * underscore ("_") after each routine name. C doesn't do this, so the + * translation is made here. Other FORTRAN compilers treat underscores + * differently. For example, a FORTRAN call to a_b gets translated to a call + * to a_b__ by g77, and to a_b_ by most other FORTRAN compilers. Thus, the + * FORTRAN names here do not use underscores. The xlf compiler in IBM AIX + * doesn't add an underscore. + * + * The matrix A is passed to UMFPACK in compressed column form, with 0-based + * indices. In FORTRAN, for an m-by-n matrix A with nz entries, the row + * indices of the first column (column 1) are in Ai (Ap (1) + 1 ... Ap (2)), + * with values in Ax (Ap (1) + 1 ... Ap (2)). The last column (column n) is + * in Ai (Ap (n) + 1 ... Ap (n+1)) and Ax (Ap (n) + 1 ... Ap (n+1)). The row + * indices in Ai are in the range 0 to m-1. They must be sorted, with no + * duplicate entries allowed. Refer to umfpack_di_triplet_to_col for a more + * flexible format for the input matrix. The following defintions apply + * for each of the routines in this file: + * + * integer m, n, Ap (n+1), Ai (nz), symbolic, numeric, filenum, status + * double precision Ax (nz), control (20), info (90), x (n), b (n) + * + * UMFPACK's status is returned in either a status argument, or in info (1). + * It is zero if everything is OK, 1 if the matrix is singular (this is a + * warning, not an error), and negative if an error occurred. See umfpack.h + * for more details on the contents of the control and info arrays, and the + * value of the sys argument. + * + * For the Numeric and Symbolic handles, it's probably safe to assume that a + * FORTRAN integer is sufficient to store a C pointer. If that doesn't work, + * try defining numeric and symbolic as integer arrays of size 2, or as + * integer*8, in the FORTRAN routine that calls these wrapper routines. + * The latter is required on Solaris, SGI IRIX, and IBM AIX when UMFPACK is + * compiled in 64-bit mode. + * + * If you want to use 64-bit integers, try compiling this file with the -DDLONG + * compiler option (via "make fortran64"). First modify your Make/Make.include + * and Make/Make. files to compile UMFPACK in LP64 mode (see the User + * Guide for details). Your FORTRAN code should use integer*8. See umf4hb64.f + * for an example. + * + * Tested with the following compilers: + * * Solaris with cc and f77 from Sun WorkShop 6 update 1 + * (32-bit and 64-bit modes) + * * SGI Irix with MIPSpro cc and f77 compilers version 7.4 + * (32-bit and 64-bit modes) + * * Linux with GNU gcc and Intel's icc, and GNU g77 and Intel's + * ifc FORTRAN compiler. See the comments above about g77 and + * underscores. Only supports 32-bit mode. + * * IBM AIX xlc and xlf compilers. + * (32-bit and 64-bit modes) + */ + +#include "umfpack.h" +#include +#include +#ifdef NULL +#undef NULL +#endif +#define NULL 0 +#define LEN 200 + +/* -------------------------------------------------------------------------- */ +/* integer type: int or long */ +/* -------------------------------------------------------------------------- */ + +#if defined (DLONG) + +#define Int long +#define UMFPACK_defaults umfpack_dl_defaults +#define UMFPACK_free_numeric umfpack_dl_free_numeric +#define UMFPACK_free_symbolic umfpack_dl_free_symbolic +#define UMFPACK_numeric umfpack_dl_numeric +#define UMFPACK_report_control umfpack_dl_report_control +#define UMFPACK_report_info umfpack_dl_report_info +#define UMFPACK_save_numeric umfpack_dl_save_numeric +#define UMFPACK_save_symbolic umfpack_dl_save_symbolic +#define UMFPACK_load_numeric umfpack_dl_load_numeric +#define UMFPACK_load_symbolic umfpack_dl_load_symbolic +#define UMFPACK_scale umfpack_dl_scale +#define UMFPACK_solve umfpack_dl_solve +#define UMFPACK_symbolic umfpack_dl_symbolic + +#else + +#define Int int +#define UMFPACK_defaults umfpack_di_defaults +#define UMFPACK_free_numeric umfpack_di_free_numeric +#define UMFPACK_free_symbolic umfpack_di_free_symbolic +#define UMFPACK_numeric umfpack_di_numeric +#define UMFPACK_report_control umfpack_di_report_control +#define UMFPACK_report_info umfpack_di_report_info +#define UMFPACK_save_numeric umfpack_di_save_numeric +#define UMFPACK_save_symbolic umfpack_di_save_symbolic +#define UMFPACK_load_numeric umfpack_di_load_numeric +#define UMFPACK_load_symbolic umfpack_di_load_symbolic +#define UMFPACK_scale umfpack_di_scale +#define UMFPACK_solve umfpack_di_solve +#define UMFPACK_symbolic umfpack_di_symbolic + +#endif + +/* -------------------------------------------------------------------------- */ +/* construct a file name from a file number (not user-callable) */ +/* -------------------------------------------------------------------------- */ + +static void make_filename (Int filenum, char *prefix, char *filename) +{ + char *psrc, *pdst ; +#ifdef DLONG + sprintf (filename, "%s%ld.umf", prefix, filenum) ; +#else + sprintf (filename, "%s%d.umf", prefix, filenum) ; +#endif + /* remove any spaces in the filename */ + pdst = filename ; + for (psrc = filename ; *psrc ; psrc++) + { + if (!isspace (*psrc)) *pdst++ = *psrc ; + } + *pdst = '\0' ; +} + +/* ========================================================================== */ +/* === with underscore ====================================================== */ +/* ========================================================================== */ + +/* Solaris, Linux, and SGI IRIX. Probably Compaq Alpha as well. */ + +/* -------------------------------------------------------------------------- */ +/* umf4def: set default control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4def (control) */ + +void umf4def_ (double Control [UMFPACK_CONTROL]) +{ + UMFPACK_defaults (Control) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4pcon: print control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4pcon (control) */ + +void umf4pcon_ (double Control [UMFPACK_CONTROL]) +{ + fflush (stdout) ; + UMFPACK_report_control (Control) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4sym: pre-ordering and symbolic factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4sym (m, n, Ap, Ai, Ax, symbolic, control, info) */ + +void umf4sym_ (Int *m, Int *n, Int Ap [ ], Int Ai [ ], + double Ax [ ], void **Symbolic, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_symbolic (*m, *n, Ap, Ai, Ax, Symbolic, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4num: numeric factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) */ + +void umf4num_ (Int Ap [ ], Int Ai [ ], double Ax [ ], + void **Symbolic, void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_numeric (Ap, Ai, Ax, *Symbolic, Numeric, Control, Info); +} + +/* -------------------------------------------------------------------------- */ +/* umf4solr: solve a linear system with iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4solr (sys, Ap, Ai, Ax, x, b, numeric, control, info) */ + +void umf4solr_ (Int *sys, Int Ap [ ], Int Ai [ ], double Ax [ ], + double x [ ], double b [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_solve (*sys, Ap, Ai, Ax, x, b, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4sol: solve a linear system without iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4sol (sys, x, b, numeric, control, info) */ + +void umf4sol_ (Int *sys, double x [ ], double b [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + Control [UMFPACK_IRSTEP] = 0 ; + (void) UMFPACK_solve (*sys, (Int *) NULL, (Int *) NULL, (double *) NULL, + x, b, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4scal: scale a vector using UMFPACK's scale factors */ +/* -------------------------------------------------------------------------- */ + +/* call umf4scal (x, b, numeric, status) */ + +void umf4scal_ (double x [ ], double b [ ], void **Numeric, Int *status) +{ + *status = UMFPACK_scale (x, b, *Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4pinf: print info */ +/* -------------------------------------------------------------------------- */ + +/* call umf4pinf (control) */ + +void umf4pinf_ (double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + fflush (stdout) ; + UMFPACK_report_info (Control, Info) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4fnum: free the Numeric object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4fnum (numeric) */ + +void umf4fnum_ (void **Numeric) +{ + UMFPACK_free_numeric (Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4fsym: free the Symbolic object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4fsym (symbolic) */ + +void umf4fsym_ (void **Symbolic) +{ + UMFPACK_free_symbolic (Symbolic) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4snum: save the Numeric object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4snum (numeric, filenum, status) */ + +void umf4snum_ (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_save_numeric (*Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4ssym: save the Symbolic object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4ssym (symbolic, filenum, status) */ + +void umf4ssym_ (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_save_symbolic (*Symbolic, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4lnum: load the Numeric object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4lnum (numeric, filenum, status) */ + +void umf4lnum_ (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_load_numeric (Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4lsym: load the Symbolic object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4lsym (symbolic, filenum, status) */ + +void umf4lsym_ (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_load_symbolic (Symbolic, filename) ; +} + +/* ========================================================================== */ +/* === with no underscore =================================================== */ +/* ========================================================================== */ + +/* IBM AIX. Probably Microsoft Windows and HP Unix as well. */ + +/* -------------------------------------------------------------------------- */ +/* umf4def: set default control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4def (control) */ + +void umf4def (double Control [UMFPACK_CONTROL]) +{ + UMFPACK_defaults (Control) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4pcon: print control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4pcon (control) */ + +void umf4pcon (double Control [UMFPACK_CONTROL]) +{ + fflush (stdout) ; + UMFPACK_report_control (Control) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4sym: pre-ordering and symbolic factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4sym (m, n, Ap, Ai, Ax, symbolic, control, info) */ + +void umf4sym (Int *m, Int *n, Int Ap [ ], Int Ai [ ], + double Ax [ ], void **Symbolic, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_symbolic (*m, *n, Ap, Ai, Ax, Symbolic, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4num: numeric factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) */ + +void umf4num (Int Ap [ ], Int Ai [ ], double Ax [ ], + void **Symbolic, void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_numeric (Ap, Ai, Ax, *Symbolic, Numeric, Control, Info); +} + +/* -------------------------------------------------------------------------- */ +/* umf4solr: solve a linear system with iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4solr (sys, Ap, Ai, Ax, x, b, numeric, control, info) */ + +void umf4solr (Int *sys, Int Ap [ ], Int Ai [ ], double Ax [ ], + double x [ ], double b [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_solve (*sys, Ap, Ai, Ax, x, b, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4sol: solve a linear system without iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4sol (sys, x, b, numeric, control, info) */ + +void umf4sol (Int *sys, double x [ ], double b [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + Control [UMFPACK_IRSTEP] = 0 ; + (void) UMFPACK_solve (*sys, (Int *) NULL, (Int *) NULL, (double *) NULL, + x, b, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4scal: scale a vector using UMFPACK's scale factors */ +/* -------------------------------------------------------------------------- */ + +/* call umf4scal (x, b, numeric, status) */ + +void umf4scal (double x [ ], double b [ ], void **Numeric, Int *status) +{ + *status = UMFPACK_scale (x, b, *Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4pinf: print info */ +/* -------------------------------------------------------------------------- */ + +/* call umf4pinf (control) */ + +void umf4pinf (double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + fflush (stdout) ; + UMFPACK_report_info (Control, Info) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4fnum: free the Numeric object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4fnum (numeric) */ + +void umf4fnum (void **Numeric) +{ + UMFPACK_free_numeric (Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4fsym: free the Symbolic object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4fsym (symbolic) */ + +void umf4fsym (void **Symbolic) +{ + UMFPACK_free_symbolic (Symbolic) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4snum: save the Numeric object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4snum (numeric, filenum, status) */ + +void umf4snum (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_save_numeric (*Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4ssym: save the Symbolic object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4ssym (symbolic, filenum, status) */ + +void umf4ssym (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_save_symbolic (*Symbolic, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4lnum: load the Numeric object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4lnum (numeric, filenum, status) */ + +void umf4lnum (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_load_numeric (Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4lsym: load the Symbolic object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4lsym (symbolic, filenum, status) */ + +void umf4lsym (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_load_symbolic (Symbolic, filename) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77zwrapper.c b/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77zwrapper.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4_f77zwrapper.c @@ -0,0 +1,462 @@ +/* ========================================================================== */ +/* === umf4_f77zwrapper ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* FORTRAN interface for the C-callable UMFPACK library (complex / int version + * only and complex / long versions only). This is HIGHLY non-portable. You + * will need to modify this depending on how your FORTRAN and C compilers + * behave. + * + * See umf4z_f77wrapper.c for more information. + * + * The complex values are provided in two separate arrays. Ax contains the + * real part and Az contains the imaginary part. The solution vector is in + * x (the real part) and xz (the imaginary part. b is the real part of the + * right-hand-side and bz is the imaginary part. Does not support the + * packed complex type. + */ + +#include "umfpack.h" +#include +#include +#ifdef NULL +#undef NULL +#endif +#define NULL 0 +#define LEN 200 + +/* -------------------------------------------------------------------------- */ +/* integer type: int or long */ +/* -------------------------------------------------------------------------- */ + +#if defined (ZLONG) + +#define Int long +#define UMFPACK_defaults umfpack_zl_defaults +#define UMFPACK_free_numeric umfpack_zl_free_numeric +#define UMFPACK_free_symbolic umfpack_zl_free_symbolic +#define UMFPACK_numeric umfpack_zl_numeric +#define UMFPACK_report_control umfpack_zl_report_control +#define UMFPACK_report_info umfpack_zl_report_info +#define UMFPACK_save_numeric umfpack_zl_save_numeric +#define UMFPACK_save_symbolic umfpack_zl_save_symbolic +#define UMFPACK_load_numeric umfpack_zl_load_numeric +#define UMFPACK_load_symbolic umfpack_zl_load_symbolic +#define UMFPACK_scale umfpack_zl_scale +#define UMFPACK_solve umfpack_zl_solve +#define UMFPACK_symbolic umfpack_zl_symbolic + +#else + +#define Int int +#define UMFPACK_defaults umfpack_zi_defaults +#define UMFPACK_free_numeric umfpack_zi_free_numeric +#define UMFPACK_free_symbolic umfpack_zi_free_symbolic +#define UMFPACK_numeric umfpack_zi_numeric +#define UMFPACK_report_control umfpack_zi_report_control +#define UMFPACK_report_info umfpack_zi_report_info +#define UMFPACK_save_numeric umfpack_zi_save_numeric +#define UMFPACK_save_symbolic umfpack_zi_save_symbolic +#define UMFPACK_load_numeric umfpack_zi_load_numeric +#define UMFPACK_load_symbolic umfpack_zi_load_symbolic +#define UMFPACK_scale umfpack_zi_scale +#define UMFPACK_solve umfpack_zi_solve +#define UMFPACK_symbolic umfpack_zi_symbolic + +#endif + +/* -------------------------------------------------------------------------- */ +/* construct a file name from a file number (not user-callable) */ +/* -------------------------------------------------------------------------- */ + +static void make_filename (Int filenum, char *prefix, char *filename) +{ + char *psrc, *pdst ; +#ifdef ZLONG + sprintf (filename, "%s%ld.umf", prefix, filenum) ; +#else + sprintf (filename, "%s%d.umf", prefix, filenum) ; +#endif + /* remove any spaces in the filename */ + pdst = filename ; + for (psrc = filename ; *psrc ; psrc++) + { + if (!isspace (*psrc)) *pdst++ = *psrc ; + } + *pdst = '\0' ; +} + +/* ========================================================================== */ +/* === with underscore ====================================================== */ +/* ========================================================================== */ + +/* Solaris, Linux, and SGI IRIX. Probably Compaq Alpha as well. */ + +/* -------------------------------------------------------------------------- */ +/* umf4zdef: set default control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zdef (control) */ + +void umf4zdef_ (double Control [UMFPACK_CONTROL]) +{ + UMFPACK_defaults (Control) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zpcon: print control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zpcon (control) */ + +void umf4zpcon_ (double Control [UMFPACK_CONTROL]) +{ + fflush (stdout) ; + UMFPACK_report_control (Control) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsym: pre-ordering and symbolic factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsym (m, n, Ap, Ai, Ax, Az, symbolic, control, info) */ + +void umf4zsym_ (Int *m, Int *n, Int Ap [ ], Int Ai [ ], + double Ax [ ], double Az [ ], void **Symbolic, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4znum: numeric factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4znum (Ap, Ai, Ax, Az, symbolic, numeric, control, info) */ + +void umf4znum_ (Int Ap [ ], Int Ai [ ], double Ax [ ], double Az [ ], + void **Symbolic, void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info); +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsolr: solve a linear system with iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsolr (sys, Ap, Ai, Ax, Az, x, xz, b, bz, numeric, control, info) */ + +void umf4zsolr_ (Int *sys, Int Ap [ ], Int Ai [ ], double Ax [ ], double Az [ ], + double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz, + *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsol: solve a linear system without iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsol (sys, x, xz, b, bz, numeric, control, info) */ + +void umf4zsol_ (Int *sys, double x [ ], double xz [ ], double b [ ], + double bz [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + Control [UMFPACK_IRSTEP] = 0 ; + (void) UMFPACK_solve (*sys, (Int *) NULL, (Int *) NULL, (double *) NULL, + (double *) NULL, x, xz, b, bz, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zscal: scale a vector using UMFPACK's scale factors */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zscal (x, xz, b, bz, numeric, status) */ + +void umf4zscal_ (double x [ ], double xz [ ], double b [ ], double bz [ ], + void **Numeric, Int *status) +{ + *status = UMFPACK_scale (x, xz, b, bz, *Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zpinf: print info */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zpinf (control) */ + +void umf4zpinf_ (double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + fflush (stdout) ; + UMFPACK_report_info (Control, Info) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zfnum: free the Numeric object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zfnum (numeric) */ + +void umf4zfnum_ (void **Numeric) +{ + UMFPACK_free_numeric (Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zfsym: free the Symbolic object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zfsym (symbolic) */ + +void umf4zfsym_ (void **Symbolic) +{ + UMFPACK_free_symbolic (Symbolic) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsnum: save the Numeric object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsnum (numeric, filenum, status) */ + +void umf4zsnum_ (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_save_numeric (*Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zssym: save the Symbolic object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zssym (symbolic, filenum, status) */ + +void umf4zssym_ (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_save_symbolic (*Symbolic, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zlnum: load the Numeric object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zlnum (numeric, filenum, status) */ + +void umf4zlnum_ (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_load_numeric (Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zlsym: load the Symbolic object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zlsym (symbolic, filenum, status) */ + +void umf4zlsym_ (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_load_symbolic (Symbolic, filename) ; +} + +/* ========================================================================== */ +/* === with no underscore =================================================== */ +/* ========================================================================== */ + +/* IBM AIX. Probably Microsoft Windows and HP Unix as well. */ + +/* -------------------------------------------------------------------------- */ +/* umf4zdef: set default control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zdef (control) */ + +void umf4zdef (double Control [UMFPACK_CONTROL]) +{ + UMFPACK_defaults (Control) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zpcon: print control parameters */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zpcon (control) */ + +void umf4zpcon (double Control [UMFPACK_CONTROL]) +{ + fflush (stdout) ; + UMFPACK_report_control (Control) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsym: pre-ordering and symbolic factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsym (m, n, Ap, Ai, Ax, Az, symbolic, control, info) */ + +void umf4zsym (Int *m, Int *n, Int Ap [ ], Int Ai [ ], + double Ax [ ], double Az [ ], void **Symbolic, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_symbolic (*m, *n, Ap, Ai, Ax, Az, Symbolic, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4znum: numeric factorization */ +/* -------------------------------------------------------------------------- */ + +/* call umf4znum (Ap, Ai, Ax, Az, symbolic, numeric, control, info) */ + +void umf4znum (Int Ap [ ], Int Ai [ ], double Ax [ ], double Az [ ], + void **Symbolic, void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_numeric (Ap, Ai, Ax, Az, *Symbolic, Numeric, Control, Info); +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsolr: solve a linear system with iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsolr (sys, Ap, Ai, Ax, Az, x, xz, b, bz, numeric, control, info) */ + +void umf4zsolr (Int *sys, Int Ap [ ], Int Ai [ ], double Ax [ ], double Az [ ], + double x [ ], double xz [ ], double b [ ], double bz [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + (void) UMFPACK_solve (*sys, Ap, Ai, Ax, Az, x, xz, b, bz, + *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsol: solve a linear system without iterative refinement */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsol (sys, x, xz, b, bz, numeric, control, info) */ + +void umf4zsol (Int *sys, double x [ ], double xz [ ], double b [ ], + double bz [ ], void **Numeric, + double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + Control [UMFPACK_IRSTEP] = 0 ; + (void) UMFPACK_solve (*sys, (Int *) NULL, (Int *) NULL, (double *) NULL, + (double *) NULL, x, xz, b, bz, *Numeric, Control, Info) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zscal: scale a vector using UMFPACK's scale factors */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zscal (x, xz, b, bz, numeric, status) */ + +void umf4zscal (double x [ ], double xz [ ], double b [ ], double bz [ ], + void **Numeric, Int *status) +{ + *status = UMFPACK_scale (x, xz, b, bz, *Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zpinf: print info */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zpinf (control) */ + +void umf4zpinf (double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + fflush (stdout) ; + UMFPACK_report_info (Control, Info) ; + fflush (stdout) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zfnum: free the Numeric object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zfnum (numeric) */ + +void umf4zfnum (void **Numeric) +{ + UMFPACK_free_numeric (Numeric) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zfsym: free the Symbolic object */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zfsym (symbolic) */ + +void umf4zfsym (void **Symbolic) +{ + UMFPACK_free_symbolic (Symbolic) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zsnum: save the Numeric object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zsnum (numeric, filenum, status) */ + +void umf4zsnum (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_save_numeric (*Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zssym: save the Symbolic object to a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zssym (symbolic, filenum, status) */ + +void umf4zssym (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_save_symbolic (*Symbolic, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zlnum: load the Numeric object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zlnum (numeric, filenum, status) */ + +void umf4zlnum (void **Numeric, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "n", filename) ; + *status = UMFPACK_load_numeric (Numeric, filename) ; +} + +/* -------------------------------------------------------------------------- */ +/* umf4zlsym: load the Symbolic object from a file */ +/* -------------------------------------------------------------------------- */ + +/* call umf4zlsym (symbolic, filenum, status) */ + +void umf4zlsym (void **Symbolic, Int *filenum, Int *status) +{ + char filename [LEN] ; + make_filename (*filenum, "s", filename) ; + *status = UMFPACK_load_symbolic (Symbolic, filename) ; +} + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.f b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.f @@ -0,0 +1,353 @@ +c======================================================================= +c== umf4hb ============================================================= +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c umf4hb: +c read a sparse matrix in the Harwell/Boeing format, factorizes +c it, and solves Ax=b. Also saves and loads the factors to/from a +c file. Saving to a file is not required, it's just here to +c demonstrate how to use this feature of UMFPACK. This program +c only works on square RUA-type matrices. +c +c This is HIGHLY non-portable. It may not work with your C and +c FORTRAN compilers. See umf4_f77wrapper.c for more details. +c +c usage (for example): +c +c in a Unix shell: +c umf4hb < HB/arc130.rua + + integer + $ nzmax, nmax + parameter (nzmax = 5000000, nmax = 160000) + integer + $ Ap (nmax), Ai (nzmax), n, nz, totcrd, ptrcrd, i, j, p, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs, nzrhs, nel, + $ numeric, symbolic, status, sys, filenum + + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + double precision Ax (nzmax), x (nmax), b (nmax), aij, xj, + $ r (nmax), control (20), info (90) + character rhstyp*3 + +c ---------------------------------------------------------------- +c read the Harwell/Boeing matrix +c ---------------------------------------------------------------- + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp, nrhs, nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + print *, 'Matrix key: ', key + + n = nrow + if (type .ne. 'RUA' .or. nrow .ne. ncol) then + print *, 'Error: can only handle square RUA matrices' + stop + endif + if (n .ge. nmax .or. nz .gt. nzmax) then + print *, ' Matrix too big!' + stop + endif + +c read the matrix (1-based) + read (5, ptrfmt, err = 998) (Ap (p), p = 1, ncol+1) + read (5, indfmt, err = 998) (Ai (p), p = 1, nz) + read (5, valfmt, err = 998) (Ax (p), p = 1, nz) + +c ---------------------------------------------------------------- +c create the right-hand-side, assume x (i) = 1 + i/n +c ---------------------------------------------------------------- + + do 30 i = 1,n + b (i) = 0 +30 continue +c b = A*x + do 50 j = 1,n + xj = j + xj = 1 + xj / n + do 40 p = Ap (j), Ap (j+1)-1 + i = Ai (p) + aij = Ax (p) + b (i) = b (i) + aij * xj +40 continue +50 continue + +c ---------------------------------------------------------------- +c convert from 1-based to 0-based +c ---------------------------------------------------------------- + + do 60 j = 1, n+1 + Ap (j) = Ap (j) - 1 +60 continue + do 70 p = 1, nz + Ai (p) = Ai (p) - 1 +70 continue + +c ---------------------------------------------------------------- +c factor the matrix and save to a file +c ---------------------------------------------------------------- + +c set default parameters + call umf4def (control) + +c print control parameters. set control (1) to 1 to print +c error messages only + control (1) = 2 + call umf4pcon (control) + +c pre-order and symbolic analysis + call umf4sym (n, n, Ap, Ai, Ax, symbolic, control, info) + +c print statistics computed so far +c call umf4pinf (control, info) could also be done. + print 80, info (1), info (16), + $ (info (21) * info (4)) / 2**20, + $ (info (22) * info (4)) / 2**20, + $ info (23), info (24), info (25) +80 format ('symbolic analysis:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, ' (sec)'/, + $ ' estimates (upper bound) for numeric LU:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4sym error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sym: ', info (1) + stop + endif + +c numeric factorization + call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) + +c print statistics for the numeric factorization +c call umf4pinf (control, info) could also be done. + print 90, info (1), info (66), + $ (info (41) * info (4)) / 2**20, + $ (info (42) * info (4)) / 2**20, + $ info (43), info (44), info (45) +90 format ('numeric factorization:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, /, + $ ' actual numeric LU statistics:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4num error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4num: ', info (1) + stop + endif + +c save the symbolic analysis to the file s0.umf +c note that this is not needed until another matrix is +c factorized, below. + filenum = 0 + call umf4ssym (symbolic, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4ssym: ', status + stop + endif + +c save the LU factors to the file n0.umf + call umf4snum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4snum: ', status + stop + endif + +c free the symbolic analysis + call umf4fsym (symbolic) + +c free the numeric factorization + call umf4fnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c ---------------------------------------------------------------- +c load the LU factors back in, and solve the system +c ---------------------------------------------------------------- + +c At this point the program could terminate and load the LU +C factors (numeric) from the n0.umf file, and solve the +c system (see below). Note that the symbolic object is not +c required. + +c load the numeric factorization back in (filename: n0.umf) + call umf4lnum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4lnum: ', status + stop + endif + +c solve Ax=b, without iterative refinement + sys = 0 + call umf4sol (sys, x, b, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c free the numeric factorization + call umf4fnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c print final statistics + call umf4pinf (control, info) + +c print the residual. x (i) should be 1 + i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + +c ---------------------------------------------------------------- +c load the symbolic analysis back in, and factorize a new matrix +c ---------------------------------------------------------------- + +c Again, the program could terminate here, recreate the matrix, +c and refactorize. Note that umf4sym is not called. + +c load the symbolic factorization back in (filename: s0.umf) + call umf4lsym (symbolic, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4lsym: ', status + stop + endif + +c arbitrarily change the values of the matrix but not the pattern + do 100 p = 1, nz + Ax (p) = Ax (p) + 3.14159 / 100.0 +100 continue + +c numeric factorization of the modified matrix + call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4num: ', info (1) + stop + endif + +c free the symbolic analysis + call umf4fsym (symbolic) + +c create a new right-hand-side, assume x (i) = 7 - i/n + do 110 i = 1,n + b (i) = 0 +110 continue +c b = A*x, with the modified matrix A (note that A is now 0-based) + do 130 j = 1,n + xj = j + xj = 7 - xj / n + do 120 p = Ap (j) + 1, Ap (j+1) + i = Ai (p) + 1 + aij = Ax (p) + b (i) = b (i) + aij * xj +120 continue +130 continue + +c ---------------------------------------------------------------- +c solve Ax=b, with iterative refinement +c ---------------------------------------------------------------- + + sys = 0 + call umf4solr (sys, Ap, Ai, Ax, x, b, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4solr: ', info (1) + stop + endif + +c print the residual. x (i) should be 7 - i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + +c ---------------------------------------------------------------- +c solve Ax=b, without iterative refinement, broken into steps +c ---------------------------------------------------------------- + +c the factorization is PAQ=LU, PRAQ=LU, or P(R\A)Q=LU. + +c x = R*b (or x=R\b, or x=b, as appropriate) + call umf4scal (x, b, numeric, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4scal: ', status + stop + endif + +c solve P'Lr=x for r (using r as workspace) + sys = 3 + call umf4sol (sys, r, x, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c solve UQ'x=r for x + sys = 9 + call umf4sol (sys, x, r, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c free the numeric factorization + call umf4fnum (numeric) + +c print the residual. x (i) should be 7 - i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + + stop +998 print *, 'Read error: Harwell/Boeing matrix' + stop + end + +c======================================================================= +c== resid ============================================================== +c======================================================================= + +c Compute the residual, r = Ax-b, its max-norm, and print the max-norm +C Note that A is zero-based. + + subroutine resid (n, nz, Ap, Ai, Ax, x, b, r) + integer + $ n, nz, Ap (n+1), Ai (n), j, i, p + double precision Ax (nz), x (n), b (n), r (n), rmax, aij + + do 10 i = 1, n + r (i) = -b (i) +10 continue + + do 30 j = 1,n + do 20 p = Ap (j) + 1, Ap (j+1) + i = Ai (p) + 1 + aij = Ax (p) + r (i) = r (i) + aij * x (j) +20 continue +30 continue + + rmax = 0 + do 40 i = 1, n + rmax = max (rmax, r (i)) +40 continue + + print *, 'norm (A*x-b): ', rmax + return + end diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.out b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb.out @@ -0,0 +1,143 @@ + Matrix key: WEST0067 + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 2 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + +symbolic analysis: + status: 0. + time: 0.00E+00 (sec) + estimates (upper bound) for numeric LU: + size of LU: 0.02 (MB) + memory needed: 0.06 (MB) + flop count: 0.14E+05 + nnz (L): 542. + nnz (U): 902. +numeric factorization: + status: 0. + time: 0.00E+00 + actual numeric LU statistics: + size of LU: 0.01 (MB) + memory needed: 0.04 (MB) + flop count: 0.26E+04 + nnz (L): 329. + nnz (U): 340. + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 67 + number of columns in matrix A: 67 + entries in matrix A: 294 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 1 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S not square or diagonal not preserved + symbolic factorization defragmentations: 1 + symbolic memory usage (Units): 1632 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 245 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 6.59006e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 1643 1574 96% + peak size (Units) 6115 3581 59% + final size (Units) 1628 685 42% + Numeric final size (Units) 2101 1125 54% + Numeric final size (MBytes) 0.0 0.0 54% + peak memory usage (Units) 7462 4928 66% + peak memory usage (MBytes) 0.1 0.0 66% + numeric factorization flops 1.41920e+04 2.58700e+03 18% + nz in L (incl diagonal) 542 329 61% + nz in U (incl diagonal) 902 340 38% + nz in L+U (incl diagonal) 1377 602 44% + largest front (# entries) 483 80 17% + largest # rows in front 21 10 48% + largest # columns in front 23 11 48% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 329 + nz in U (incl diagonal), if none dropped 340 + number of small entries dropped 0 + nonzeros on diagonal of U: 67 + min abs. value on diagonal of U: 2.74e-02 + max abs. value on diagonal of U: 2.28e+00 + estimate of reciprocal of condition number: 1.20e-02 + indices in compressed pattern: 256 + numerical values stored in Numeric object: 605 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.20400e+03 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 3.79100e+03 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + norm (A*x-b): 2.22044605E-15 + norm (A*x-b): 1.05076538E-14 + norm (A*x-b): 1.05076538E-14 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4hb64.f b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb64.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4hb64.f @@ -0,0 +1,353 @@ +c======================================================================= +c== umf4hb ============================================================= +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c umf4hb64: +c read a sparse matrix in the Harwell/Boeing format, factorizes +c it, and solves Ax=b. Also saves and loads the factors to/from a +c file. Saving to a file is not required, it's just here to +c demonstrate how to use this feature of UMFPACK. This program +c only works on square RUA-type matrices. +c +c This is HIGHLY non-portable. It may not work with your C and +c FORTRAN compilers. See umf4_f77wrapper.c for more details. +c +c usage (for example): +c +c in a Unix shell: +c umf4hb64 < HB/arc130.rua + + integer*8 + $ nzmax, nmax + parameter (nzmax = 5000000, nmax = 160000) + integer*8 + $ Ap (nmax), Ai (nzmax), n, nz, totcrd, ptrcrd, i, j, p, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs, nzrhs, nel, + $ numeric, symbolic, status, sys, filenum + + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + double precision Ax (nzmax), x (nmax), b (nmax), aij, xj, + $ r (nmax), control (20), info (90) + character rhstyp*3 + +c ---------------------------------------------------------------- +c read the Harwell/Boeing matrix +c ---------------------------------------------------------------- + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp, nrhs, nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + print *, 'Matrix key: ', key + + n = nrow + if (type .ne. 'RUA' .or. nrow .ne. ncol) then + print *, 'Error: can only handle square RUA matrices' + stop + endif + if (n .ge. nmax .or. nz .gt. nzmax) then + print *, ' Matrix too big!' + stop + endif + +c read the matrix (1-based) + read (5, ptrfmt, err = 998) (Ap (p), p = 1, ncol+1) + read (5, indfmt, err = 998) (Ai (p), p = 1, nz) + read (5, valfmt, err = 998) (Ax (p), p = 1, nz) + +c ---------------------------------------------------------------- +c create the right-hand-side, assume x (i) = 1 + i/n +c ---------------------------------------------------------------- + + do 30 i = 1,n + b (i) = 0 +30 continue +c b = A*x + do 50 j = 1,n + xj = j + xj = 1 + xj / n + do 40 p = Ap (j), Ap (j+1)-1 + i = Ai (p) + aij = Ax (p) + b (i) = b (i) + aij * xj +40 continue +50 continue + +c ---------------------------------------------------------------- +c convert from 1-based to 0-based +c ---------------------------------------------------------------- + + do 60 j = 1, n+1 + Ap (j) = Ap (j) - 1 +60 continue + do 70 p = 1, nz + Ai (p) = Ai (p) - 1 +70 continue + +c ---------------------------------------------------------------- +c factor the matrix and save to a file +c ---------------------------------------------------------------- + +c set default parameters + call umf4def (control) + +c print control parameters. set control (1) to 1 to print +c error messages only + control (1) = 2 + call umf4pcon (control) + +c pre-order and symbolic analysis + call umf4sym (n, n, Ap, Ai, Ax, symbolic, control, info) + +c print statistics computed so far +c call umf4pinf (control, info) could also be done. + print 80, info (1), info (16), + $ (info (21) * info (4)) / 2**20, + $ (info (22) * info (4)) / 2**20, + $ info (23), info (24), info (25) +80 format ('symbolic analysis:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, ' (sec)'/, + $ ' estimates (upper bound) for numeric LU:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4sym error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sym: ', info (1) + stop + endif + +c numeric factorization + call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) + +c print statistics for the numeric factorization +c call umf4pinf (control, info) could also be done. + print 90, info (1), info (66), + $ (info (41) * info (4)) / 2**20, + $ (info (42) * info (4)) / 2**20, + $ info (43), info (44), info (45) +90 format ('numeric factorization:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, /, + $ ' actual numeric LU statistics:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4num error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4num: ', info (1) + stop + endif + +c save the symbolic analysis to the file s0.umf +c note that this is not needed until another matrix is +c factorized, below. + filenum = 0 + call umf4ssym (symbolic, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4ssym: ', status + stop + endif + +c save the LU factors to the file n0.umf + call umf4snum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4snum: ', status + stop + endif + +c free the symbolic analysis + call umf4fsym (symbolic) + +c free the numeric factorization + call umf4fnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c ---------------------------------------------------------------- +c load the LU factors back in, and solve the system +c ---------------------------------------------------------------- + +c At this point the program could terminate and load the LU +C factors (numeric) from the n0.umf file, and solve the +c system (see below). Note that the symbolic object is not +c required. + +c load the numeric factorization back in (filename: n0.umf) + call umf4lnum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4lnum: ', status + stop + endif + +c solve Ax=b, without iterative refinement + sys = 0 + call umf4sol (sys, x, b, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c free the numeric factorization + call umf4fnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c print final statistics + call umf4pinf (control, info) + +c print the residual. x (i) should be 1 + i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + +c ---------------------------------------------------------------- +c load the symbolic analysis back in, and factorize a new matrix +c ---------------------------------------------------------------- + +c Again, the program could terminate here, recreate the matrix, +c and refactorize. Note that umf4sym is not called. + +c load the symbolic factorization back in (filename: s0.umf) + call umf4lsym (symbolic, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4lsym: ', status + stop + endif + +c arbitrarily change the values of the matrix but not the pattern + do 100 p = 1, nz + Ax (p) = Ax (p) + 3.14159 / 100.0 +100 continue + +c numeric factorization of the modified matrix + call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4num: ', info (1) + stop + endif + +c free the symbolic analysis + call umf4fsym (symbolic) + +c create a new right-hand-side, assume x (i) = 7 - i/n + do 110 i = 1,n + b (i) = 0 +110 continue +c b = A*x, with the modified matrix A (note that A is now 0-based) + do 130 j = 1,n + xj = j + xj = 7 - xj / n + do 120 p = Ap (j) + 1, Ap (j+1) + i = Ai (p) + 1 + aij = Ax (p) + b (i) = b (i) + aij * xj +120 continue +130 continue + +c ---------------------------------------------------------------- +c solve Ax=b, with iterative refinement +c ---------------------------------------------------------------- + + sys = 0 + call umf4solr (sys, Ap, Ai, Ax, x, b, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4solr: ', info (1) + stop + endif + +c print the residual. x (i) should be 7 - i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + +c ---------------------------------------------------------------- +c solve Ax=b, without iterative refinement, broken into steps +c ---------------------------------------------------------------- + +c the factorization is PAQ=LU, PRAQ=LU, or P(R\A)Q=LU. + +c x = R*b (or x=R\b, or x=b, as appropriate) + call umf4scal (x, b, numeric, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4scal: ', status + stop + endif + +c solve P'Lr=x for r (using r as workspace) + sys = 3 + call umf4sol (sys, r, x, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c solve UQ'x=r for x + sys = 9 + call umf4sol (sys, x, r, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4sol: ', info (1) + stop + endif + +c free the numeric factorization + call umf4fnum (numeric) + +c print the residual. x (i) should be 7 - i/n + call resid (n, nz, Ap, Ai, Ax, x, b, r) + + stop +998 print *, 'Read error: Harwell/Boeing matrix' + stop + end + +c======================================================================= +c== resid ============================================================== +c======================================================================= + +c Compute the residual, r = Ax-b, its max-norm, and print the max-norm +C Note that A is zero-based. + + subroutine resid (n, nz, Ap, Ai, Ax, x, b, r) + integer*8 + $ n, nz, Ap (n+1), Ai (n), j, i, p + double precision Ax (nz), x (n), b (n), r (n), rmax, aij + + do 10 i = 1, n + r (i) = -b (i) +10 continue + + do 30 j = 1,n + do 20 p = Ap (j) + 1, Ap (j+1) + i = Ai (p) + 1 + aij = Ax (p) + r (i) = r (i) + aij * x (j) +20 continue +30 continue + + rmax = 0 + do 40 i = 1, n + rmax = max (rmax, r (i)) +40 continue + + print *, 'norm (A*x-b): ', rmax + return + end diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.f b/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.f new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.f @@ -0,0 +1,279 @@ +c======================================================================= +c== umf4zhb ============================================================ +c======================================================================= + +c----------------------------------------------------------------------- +c UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE +c Dept, Univ. of Florida. All Rights Reserved. See ../Doc/License for +c License. web: http://www.cise.ufl.edu/research/sparse/umfpack +c----------------------------------------------------------------------- + +c umf4zhb: +c read a sparse matrix in the Harwell/Boeing format, factorizes +c it, and solves Ax=b. Also saves and loads the factors to/from a +c file. Saving to a file is not required, it's just here to +c demonstrate how to use this feature of UMFPACK. This program +c only works on square CUA-type matrices. +c +c This is HIGHLY non-portable. It may not work with your C and +c FORTRAN compilers. See umf4z_f77wrapper.c for more details. +c +c usage (for example): +c +c in a Unix shell: +c umf4zhb < HB/arc130.cua + + integer + $ nzmax, nmax + parameter (nzmax = 5000000, nmax = 160000) + integer + $ Ap (nmax), Ai (nzmax), n, nz, totcrd, ptrcrd, i, j, p, + $ indcrd, valcrd, rhscrd, ncol, nrow, nrhs, nzrhs, nel, + $ numeric, symbolic, status, sys, filenum + + character title*72, key*30, type*3, ptrfmt*16, + $ indfmt*16, valfmt*20, rhsfmt*20 + double precision Ax (nzmax), x (nmax), b (nmax), + $ control (20), info (90) + complex*16 AA (nzmax), XX (nmax), BB (nmax), r (nmax), aij, xj + double precision Az (nmax), xz (nmax), bz (nmax), xi, xr + character rhstyp*3 + +c ---------------------------------------------------------------- +c read the Harwell/Boeing matrix +c ---------------------------------------------------------------- + + read (5, 10, err = 998) + $ title, key, + $ totcrd, ptrcrd, indcrd, valcrd, rhscrd, + $ type, nrow, ncol, nz, nel, + $ ptrfmt, indfmt, valfmt, rhsfmt + if (rhscrd .gt. 0) then +c new Harwell/Boeing format: + read (5, 20, err = 998) rhstyp, nrhs, nzrhs + endif +10 format (a72, a8 / 5i14 / a3, 11x, 4i14 / 2a16, 2a20) +20 format (a3, 11x, 2i14) + + print *, 'Matrix key: ', key + + n = nrow + if (type .ne. 'CUA' .or. nrow .ne. ncol) then + print *, 'Error: can only handle square CUA matrices' + stop + endif + if (n .ge. nmax .or. nz .gt. nzmax) then + print *, ' Matrix too big!' + stop + endif + +c read the matrix (1-based) + read (5, ptrfmt, err = 998) (Ap (p), p = 1, ncol+1) + read (5, indfmt, err = 998) (Ai (p), p = 1, nz) + read (5, valfmt, err = 998) (AA (p), p = 1, nz) + + do 15 p = 1, nz + Ax (p) = dble (AA (p)) + Az (p) = imag (AA (p)) +15 continue + +c ---------------------------------------------------------------- +c create the right-hand-side, assume +c x (i) = (1 + i/n), (n + i/100) +c ---------------------------------------------------------------- + + do 30 i = 1,n + BB (i) = 0 +30 continue +c b = A*x + do 50 j = 1,n + xr = j + xi = n + xi = xi + xr/100 + xr = 1 + xr / n + xj = dcmplx (xr, xi) + do 40 p = Ap (j), Ap (j+1)-1 + i = Ai (p) + aij = AA (p) + BB (i) = BB (i) + aij * xj +40 continue +50 continue + do 32 i = 1,n + b (i) = dble (BB (i)) + bz (i) = imag (BB (i)) +32 continue + +c ---------------------------------------------------------------- +c convert from 1-based to 0-based +c ---------------------------------------------------------------- + + do 60 j = 1, n+1 + Ap (j) = Ap (j) - 1 +60 continue + do 70 p = 1, nz + Ai (p) = Ai (p) - 1 +70 continue + +c ---------------------------------------------------------------- +c factor the matrix and save to a file +c ---------------------------------------------------------------- + +c set default parameters + call umf4zdef (control) + +c print control parameters. set control (1) to 1 to print +c error messages only + control (1) = 2 + call umf4zpcon (control) + +c pre-order and symbolic analysis + call umf4zsym (n, n, Ap, Ai, Ax, Az, symbolic, control, info) + +c print statistics computed so far +c call umf4zpinf (control, info) could also be done. + print 80, info (1), info (16), + $ (info (21) * info (4)) / 2**20, + $ (info (22) * info (4)) / 2**20, + $ info (23), info (24), info (25) +80 format ('symbolic analysis:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, ' (sec)'/, + $ ' estimates (upper bound) for numeric LU:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4zsym error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4zsym: ', info (1) + stop + endif + +c numeric factorization + call umf4znum (Ap, Ai, Ax, Az, symbolic, numeric, control, info) + +c print statistics for the numeric factorization +c call umf4zpinf (control, info) could also be done. + print 90, info (1), info (66), + $ (info (41) * info (4)) / 2**20, + $ (info (42) * info (4)) / 2**20, + $ info (43), info (44), info (45) +90 format ('numeric factorization:',/, + $ ' status: ', f5.0, /, + $ ' time: ', e10.2, /, + $ ' actual numeric LU statistics:', /, + $ ' size of LU: ', f10.2, ' (MB)', /, + $ ' memory needed: ', f10.2, ' (MB)', /, + $ ' flop count: ', e10.2, / + $ ' nnz (L): ', f10.0, / + $ ' nnz (U): ', f10.0) + +c check umf4znum error condition + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4znum: ', info (1) + stop + endif + +c save the symbolic analysis to the file s42.umf +c note that this is not needed until another matrix is +c factorized, below. + filenum = 42 + call umf4zssym (symbolic, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4zssym: ', status + stop + endif + +c save the LU factors to the file n0.umf + call umf4zsnum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4zsnum: ', status + stop + endif + +c free the symbolic analysis + call umf4zfsym (symbolic) + +c free the numeric factorization + call umf4zfnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c ---------------------------------------------------------------- +c load the LU factors back in, and solve the system +c ---------------------------------------------------------------- + +c At this point the program could terminate and load the LU +C factors (numeric) from the n0.umf file, and solve the +c system (see below). Note that the symbolic object is not +c required. + +c load the numeric factorization back in (filename: n0.umf) + call umf4zlnum (numeric, filenum, status) + if (status .lt. 0) then + print *, 'Error occurred in umf4zlnum: ', status + stop + endif + +c solve Ax=b, without iterative refinement + sys = 0 + call umf4zsol (sys, x, xz, b, bz, numeric, control, info) + if (info (1) .lt. 0) then + print *, 'Error occurred in umf4zsol: ', info (1) + stop + endif + do 33 i = 1,n + XX (i) = dcmplx (x (i), xz (i)) +33 continue + +c free the numeric factorization + call umf4zfnum (numeric) + +c No LU factors (symbolic or numeric) are in memory at this point. + +c print final statistics + call umf4zpinf (control, info) + +c print the residual. x (i) should be 1 + i/n + call resid (n, nz, Ap, Ai, AA, XX, BB, r) + + stop +998 print *, 'Read error: Harwell/Boeing matrix' + stop + end + +c======================================================================= +c== resid ============================================================== +c======================================================================= + +c Compute the residual, r = Ax-b, its max-norm, and print the max-norm +C Note that A is zero-based. + + subroutine resid (n, nz, Ap, Ai, A, x, b, r) + integer + $ n, nz, Ap (n+1), Ai (n), j, i, p + complex*16 A (nz), x (n), b (n), r (n), aij + double precision rmax + + do 10 i = 1, n + r (i) = -b (i) +10 continue + + do 30 j = 1,n + do 20 p = Ap (j) + 1, Ap (j+1) + i = Ai (p) + 1 + aij = A (p) + r (i) = r (i) + aij * x (j) +20 continue +30 continue + + rmax = 0 + do 40 i = 1, n + rmax = max (rmax, abs (r (i))) +40 continue + + print *, 'norm (A*x-b): ', rmax + return + end diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.out b/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umf4zhb.out @@ -0,0 +1,160 @@ + Matrix key: QC324 + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double complex + Int (generic integer) defined as: int + + 0: print level: 2 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 16 (in bytes) + +symbolic analysis: + status: 0. + time: 0.10E-01 (sec) + estimates (upper bound) for numeric LU: + size of LU: 1.17 (MB) + memory needed: 2.40 (MB) + flop count: 0.26E+08 + nnz (L): 24027. + nnz (U): 39609. +numeric factorization: + status: 0. + time: 0.10E-01 + actual numeric LU statistics: + size of LU: 0.72 (MB) + memory needed: 1.14 (MB) + flop count: 0.14E+08 + nnz (L): 23247. + nnz (U): 23247. + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 324 + number of columns in matrix A: 324 + entries in matrix A: 26730 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: symmetric + ordering used: amd on A+A' + modify Q during factorization: no + prefer diagonal pivoting: yes + pivots with zero Markowitz cost: 0 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 324 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 324 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 26406 + nz on diagonal of matrix S: 324 + fraction of nz on diagonal: 1.000000 + AMD statistics, for strict diagonal pivoting: + est. flops for LU factorization: 1.55342e+07 + est. nz in L+U (incl. diagonal): 47730 + est. largest front (# entries): 14641 + est. max nz in any column of L: 121 + number of "dense" rows/columns in S+S': 0 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 63466 + symbolic memory usage (MBytes): 0.5 + Symbolic size (Units): 1418 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.01 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 2.55982e-01 + maximum sum (abs (rows of A)): 1.82217e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 98017 97692 100% + peak size (Units) 307744 142557 46% + final size (Units) 150384 92058 61% + Numeric final size (Units) 153181 94693 62% + Numeric final size (MBytes) 1.2 0.7 62% + peak memory usage (Units) 314850 149663 48% + peak memory usage (MBytes) 2.4 1.1 48% + numeric factorization flops 2.56313e+07 1.43519e+07 56% + nz in L (incl diagonal) 24027 23247 97% + nz in U (incl diagonal) 39609 23247 59% + nz in L+U (incl diagonal) 63312 46170 73% + largest front (# entries) 19723 6724 34% + largest # rows in front 121 82 68% + largest # columns in front 163 82 50% + + initial allocation ratio used: 1.2 + # of forced updates due to frontal growth: 0 + number of off-diagonal pivots: 0 + nz in L (incl diagonal), if none dropped 23247 + nz in U (incl diagonal), if none dropped 23247 + number of small entries dropped 0 + nonzeros on diagonal of U: 324 + min abs. value on diagonal of U: 5.47e-03 + max abs. value on diagonal of U: 8.25e-01 + estimate of reciprocal of condition number: 6.63e-03 + indices in compressed pattern: 485 + numerical values stored in Numeric object: 46170 + numeric factorization defragmentations: 0 + numeric factorization reallocations: 0 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.01 + numeric factorization wallclock time (sec): 0.02 + numeric factorization mflops (CPU time): 1435.19 + numeric factorization mflops (wallclock): 717.60 + symbolic + numeric CPU time (sec): 0.02 + symbolic + numeric mflops (CPU time): 717.60 + symbolic + numeric wall clock time (sec): 0.02 + symbolic + numeric mflops (wall clock): 717.60 + + solve flops: 3.70332e+05 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.47223e+07 + total symbolic + numeric + solve CPU time: 0.02 + total symbolic + numeric + solve mflops (CPU): 736.11 + total symbolic+numeric+solve wall clock time: 0.02 + total symbolic+numeric+solve mflops(wallclock) 736.11 + + norm (A*x-b): 2.96487174E-13 diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.c @@ -0,0 +1,759 @@ +/* ========================================================================== */ +/* === umfpack_di_demo ====================================================== */ +/* ========================================================================== */ + + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + A demo of UMFPACK: umfpack_di_* version. + + First, factor and solve a 5-by-5 system, Ax=b, using default parameters. + Then solve A'x=b using the factors of A. Modify one entry (A (1,4) = 0, + where the row and column indices range from 0 to 4. The pattern of A + has not changed (it has explicitly zero entry), so a reanalysis with + umfpack_di_symbolic does not need to be done. Refactorize (with + umfpack_di_numeric), and solve Ax=b. Note that the pivot ordering has + changed. Next, change all of the entries in A, but not the pattern. + + Finally, compute C = A', and do the symbolic and numeric factorization of C. + Factorizing A' can sometimes be better than factorizing A itself (less work + and memory usage). Solve C'x=b twice; the solution is the same as the + solution to Ax=b. + + A note about zero-sized arrays: UMFPACK uses many user-provided arrays of + size n (order of the matrix), and of size nz (the number of nonzeros in a + matrix). n cannot be zero; UMFPACK does not handle zero-dimensioned arrays. + However, nz can be zero. If you attempt to malloc an array of size nz = 0, + however, malloc will return a null pointer which UMFPACK will report as a + "missing argument." Thus, nz1 in this code is set to MAX (nz,1), and + similarly for lnz and unz. Lnz can never be zero, however, since L is always + unit diagonal. +*/ + +/* -------------------------------------------------------------------------- */ +/* definitions */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "umfpack.h" + +#define ABS(x) ((x) >= 0 ? (x) : -(x)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ +/* triplet form of the matrix. The triplets can be in any order. */ +/* -------------------------------------------------------------------------- */ + +static int n = 5, nz = 12 ; +static int Arow [ ] = { 0, 4, 1, 1, 2, 2, 0, 1, 2, 3, 4, 4} ; +static int Acol [ ] = { 0, 4, 0, 2, 1, 2, 1, 4, 3, 2, 1, 2} ; +static double Aval [ ] = {2., 1., 3., 4., -1., -3., 3., 6., 2., 1., 4., 2.} ; +static double b [ ] = {8., 45., -3., 3., 19.}, x [5], r [5] ; + + +/* -------------------------------------------------------------------------- */ +/* error: print a message and exit */ +/* -------------------------------------------------------------------------- */ + +static void error +( + char *message +) +{ + printf ("\n\n====== error: %s =====\n\n", message) ; + exit (1) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the residual, r = Ax-b or r = A'x=b and return maxnorm (r) */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + int transpose, + int Ap [ ], + int Ai [ ], + double Ax [ ] +) +{ + int i, j, p ; + double norm ; + + for (i = 0 ; i < n ; i++) + { + r [i] = -b [i] ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [j] += Ax [p] * x [i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + } + } + } + norm = 0. ; + for (i = 0 ; i < n ; i++) + { + norm = MAX (ABS (r [i]), norm) ; + } + return (norm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], *Ax, *Cx, *Lx, *Ux, + *W, t [2], *Dx, rnorm, *Rb, *y, *Rs ; + int *Ap, *Ai, *Cp, *Ci, row, col, p, lnz, unz, nr, nc, *Lp, *Li, *Ui, *Up, + *P, *Q, *Lj, i, j, k, anz, nfr, nchains, *Qinit, fnpiv, lnz1, unz1, nz1, + status, *Front_npivcol, *Front_parent, *Chain_start, *Wi, *Pinit, n1, + *Chain_maxrows, *Chain_maxcols, *Front_1strow, *Front_leftmostdesc, + nzud, do_recip ; + void *Symbolic, *Numeric ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (t) ; + + printf ("\n%s demo: _di_ version\n", UMFPACK_VERSION) ; + + /* get the default control parameters */ + umfpack_di_defaults (Control) ; + + /* change the default print level for this demo */ + /* (otherwise, nothing will print) */ + Control [UMFPACK_PRL] = 6 ; + + /* print the license agreement */ + umfpack_di_report_status (Control, UMFPACK_OK) ; + Control [UMFPACK_PRL] = 5 ; + + /* print the control parameters */ + umfpack_di_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* print A and b, and convert A to column-form */ + /* ---------------------------------------------------------------------- */ + + /* print the right-hand-side */ + printf ("\nb: ") ; + (void) umfpack_di_report_vector (n, b, Control) ; + + /* print the triplet form of the matrix */ + printf ("\nA: ") ; + (void) umfpack_di_report_triplet (n, n, nz, Arow, Acol, Aval, + Control) ; + + /* convert to column form */ + nz1 = MAX (nz,1) ; /* ensure arrays are not of size zero. */ + Ap = (int *) malloc ((n+1) * sizeof (int)) ; + Ai = (int *) malloc (nz1 * sizeof (int)) ; + Ax = (double *) malloc (nz1 * sizeof (double)) ; + if (!Ap || !Ai || !Ax) + { + error ("out of memory") ; + } + + status = umfpack_di_triplet_to_col (n, n, nz, Arow, Acol, Aval, + Ap, Ai, Ax, (int *) NULL) ; + + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_triplet_to_col failed") ; + } + + /* print the column-form of A */ + printf ("\nA: ") ; + (void) umfpack_di_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_symbolic failed") ; + } + + /* print the symbolic factorization */ + + printf ("\nSymbolic factorization of A: ") ; + (void) umfpack_di_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_numeric failed") ; + } + + /* print the numeric factorization */ + printf ("\nNumeric factorization of A: ") ; + (void) umfpack_di_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_di_solve failed") ; + } + printf ("\nx (solution of Ax=b): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_get_determinant (x, r, Numeric, Info) ; + umfpack_di_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_di_get_determinant failed") ; + } + printf ("determinant: (%g", x [0]) ; + printf (") * 10^(%g)\n", r [0]) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, broken down into steps */ + /* ---------------------------------------------------------------------- */ + + /* Rb = R*b */ + Rb = (double *) malloc (n * sizeof (double)) ; + y = (double *) malloc (n * sizeof (double)) ; + if (!Rb || !y) error ("out of memory") ; + + status = umfpack_di_scale (Rb, b, Numeric) ; + if (status < 0) error ("umfpack_di_scale failed") ; + /* solve Ly = P*(Rb) */ + status = umfpack_di_solve (UMFPACK_Pt_L, Ap, Ai, Ax, y, Rb, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_di_solve failed") ; + /* solve UQ'x=y */ + status = umfpack_di_solve (UMFPACK_U_Qt, Ap, Ai, Ax, x, y, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_di_solve failed") ; + printf ("\nx (solution of Ax=b, solve is split into 3 steps): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + free (Rb) ; + free (y) ; + + /* ---------------------------------------------------------------------- */ + /* solve A'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_solve (UMFPACK_At, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_di_report_info (Control, Info) ; + if (status < 0) + { + error ("umfpack_di_solve failed") ; + } + printf ("\nx (solution of A'x=b): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify one numerical value in the column-form of A */ + /* ---------------------------------------------------------------------- */ + + /* change A (1,4), look for row index 1 in column 4. */ + row = 1 ; + col = 4 ; + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + if (row == Ai [p]) + { + printf ("\nchanging A (%d,%d) to zero\n", row, col) ; + Ax [p] = 0.0 ; + break ; + } + } + printf ("\nmodified A: ") ; + (void) umfpack_di_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* The pattern (Ap and Ai) hasn't changed, so the symbolic factorization */ + /* doesn't have to be redone, no matter how much we change Ax. */ + + /* We don't need the Numeric object any more, so free it. */ + umfpack_di_free_numeric (&Numeric) ; + + /* Note that a memory leak would have occurred if the old Numeric */ + /* had not been free'd with umfpack_di_free_numeric above. */ + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_numeric failed") ; + } + printf ("\nNumeric factorization of modified A: ") ; + (void) umfpack_di_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_di_report_info (Control, Info) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_solve failed") ; + } + printf ("\nx (with modified A): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify all of the numerical values of A, but not the pattern */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < n ; col++) + { + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + row = Ai [p] ; + printf ("changing ") ; + printf ("A (%d,%d) from %g", row, col, Ax [p]) ; + Ax [p] = Ax [p] + col*10 - row ; + printf (" to %g\n", Ax [p]) ; + } + } + printf ("\ncompletely modified A (same pattern): ") ; + (void) umfpack_di_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Symbolic object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "symbolic.umf" */ + printf ("\nSaving symbolic object:\n") ; + status = umfpack_di_save_symbolic (Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_save_symbolic failed") ; + } + printf ("\nFreeing symbolic object:\n") ; + umfpack_di_free_symbolic (&Symbolic) ; + printf ("\nLoading symbolic object:\n") ; + status = umfpack_di_load_symbolic (&Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_load_symbolic failed") ; + } + printf ("\nDone loading symbolic object\n") ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_di_free_numeric (&Numeric) ; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_numeric failed") ; + } + printf ("\nNumeric factorization of completely modified A: ") ; + (void) umfpack_di_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_di_report_info (Control, Info) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_solve failed") ; + } + printf ("\nx (with completely modified A): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free the symbolic and numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_di_free_symbolic (&Symbolic) ; + umfpack_di_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* C = transpose of A */ + /* ---------------------------------------------------------------------- */ + + Cp = (int *) malloc ((n+1) * sizeof (int)) ; + Ci = (int *) malloc (nz1 * sizeof (int)) ; + Cx = (double *) malloc (nz1 * sizeof (double)) ; + if (!Cp || !Ci || !Cx) + { + error ("out of memory") ; + } + status = umfpack_di_transpose (n, n, Ap, Ai, Ax, + (int *) NULL, (int *) NULL, Cp, Ci, Cx) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_transpose failed: ") ; + } + printf ("\nC (transpose of A): ") ; + (void) umfpack_di_report_matrix (n, n, Cp, Ci, Cx, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_symbolic (n, n, Cp, Ci, Cx, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_di_report_info (Control, Info) ; + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_symbolic failed") ; + } + printf ("\nSymbolic factorization of C: ") ; + (void) umfpack_di_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* copy the contents of Symbolic into user arrays print them */ + /* ---------------------------------------------------------------------- */ + + printf ("\nGet the contents of the Symbolic object for C:\n") ; + printf ("(compare with umfpack_di_report_symbolic output, above)\n") ; + Pinit = (int *) malloc ((n+1) * sizeof (int)) ; + Qinit = (int *) malloc ((n+1) * sizeof (int)) ; + Front_npivcol = (int *) malloc ((n+1) * sizeof (int)) ; + Front_1strow = (int *) malloc ((n+1) * sizeof (int)) ; + Front_leftmostdesc = (int *) malloc ((n+1) * sizeof (int)) ; + Front_parent = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_start = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_maxrows = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_maxcols = (int *) malloc ((n+1) * sizeof (int)) ; + if (!Pinit || !Qinit || !Front_npivcol || !Front_parent || !Chain_start || + !Chain_maxrows || !Chain_maxcols || !Front_1strow || + !Front_leftmostdesc) + { + error ("out of memory") ; + } + + status = umfpack_di_get_symbolic (&nr, &nc, &n1, &anz, &nfr, &nchains, + Pinit, Qinit, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + + if (status < 0) + { + error ("symbolic factorization invalid") ; + } + + printf ("From the Symbolic object, C is of dimension %d-by-%d\n", nr, nc); + printf (" with nz = %d, number of fronts = %d,\n", nz, nfr) ; + printf (" number of frontal matrix chains = %d\n", nchains) ; + + printf ("\nPivot columns in each front, and parent of each front:\n") ; + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fnpiv = Front_npivcol [i] ; + printf (" Front %d: parent front: %d number of pivot cols: %d\n", + i, Front_parent [i], fnpiv) ; + for (j = 0 ; j < fnpiv ; j++) + { + col = Qinit [k] ; + printf ( + " %d-th pivot column is column %d in original matrix\n", + k, col) ; + k++ ; + } + } + + printf ("\nNote that the column ordering, above, will be refined\n") ; + printf ("in the numeric factorization below. The assignment of pivot\n") ; + printf ("columns to frontal matrices will always remain unchanged.\n") ; + + printf ("\nTotal number of pivot columns in frontal matrices: %d\n", k) ; + + printf ("\nFrontal matrix chains:\n") ; + for (j = 0 ; j < nchains ; j++) + { + printf (" Frontal matrices %d to %d are factorized in a single\n", + Chain_start [j], Chain_start [j+1] - 1) ; + printf (" working array of size %d-by-%d\n", + Chain_maxrows [j], Chain_maxcols [j]) ; + } + + /* ---------------------------------------------------------------------- */ + /* numeric factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_numeric (Cp, Ci, Cx, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + error ("umfpack_di_numeric failed") ; + } + printf ("\nNumeric factorization of C: ") ; + (void) umfpack_di_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* extract the LU factors of C and print them */ + /* ---------------------------------------------------------------------- */ + + if (umfpack_di_get_lunz (&lnz, &unz, &nr, &nc, &nzud, Numeric) < 0) + { + error ("umfpack_di_get_lunz failed") ; + } + /* ensure arrays are not of zero size */ + lnz1 = MAX (lnz,1) ; + unz1 = MAX (unz,1) ; + Lp = (int *) malloc ((n+1) * sizeof (int)) ; + Lj = (int *) malloc (lnz1 * sizeof (int)) ; + Lx = (double *) malloc (lnz1 * sizeof (double)) ; + Up = (int *) malloc ((n+1) * sizeof (int)) ; + Ui = (int *) malloc (unz1 * sizeof (int)) ; + Ux = (double *) malloc (unz1 * sizeof (double)) ; + P = (int *) malloc (n * sizeof (int)) ; + Q = (int *) malloc (n * sizeof (int)) ; + Dx = (double *) NULL ; /* D vector not requested */ + Rs = (double *) malloc (n * sizeof (double)) ; + if (!Lp || !Lj || !Lx || !Up || !Ui || !Ux || !P || !Q || !Rs) + { + error ("out of memory") ; + } + status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, + P, Q, Dx, &do_recip, Rs, Numeric) ; + if (status < 0) + { + error ("umfpack_di_get_numeric failed") ; + } + + printf ("\nL (lower triangular factor of C): ") ; + (void) umfpack_di_report_matrix (n, n, Lp, Lj, Lx, 0, Control) ; + printf ("\nU (upper triangular factor of C): ") ; + (void) umfpack_di_report_matrix (n, n, Up, Ui, Ux, 1, Control) ; + printf ("\nP: ") ; + (void) umfpack_di_report_perm (n, P, Control) ; + printf ("\nQ: ") ; + (void) umfpack_di_report_perm (n, Q, Control) ; + printf ("\nScale factors: row i of A is to be ") ; + if (do_recip) + { + printf ("multiplied by the ith scale factor\n") ; + } + else + { + printf ("divided by the ith scale factor\n") ; + } + for (i = 0 ; i < n ; i++) printf ("%d: %g\n", i, Rs [i]) ; + + /* ---------------------------------------------------------------------- */ + /* convert L to triplet form and print it */ + /* ---------------------------------------------------------------------- */ + + /* Note that L is in row-form, so it is the row indices that are created */ + /* by umfpack_di_col_to_triplet. */ + + printf ("\nConverting L to triplet form, and printing it:\n") ; + Li = (int *) malloc (lnz1 * sizeof (int)) ; + if (!Li) + { + error ("out of memory") ; + } + if (umfpack_di_col_to_triplet (n, Lp, Li) < 0) + { + error ("umfpack_di_col_to_triplet failed") ; + } + printf ("\nL, in triplet form: ") ; + (void) umfpack_di_report_triplet (n, n, lnz, Li, Lj, Lx, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Numeric object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "numeric.umf" */ + printf ("\nSaving numeric object:\n") ; + status = umfpack_di_save_numeric (Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_save_numeric failed") ; + } + printf ("\nFreeing numeric object:\n") ; + umfpack_di_free_numeric (&Numeric) ; + printf ("\nLoading numeric object:\n") ; + status = umfpack_di_load_numeric (&Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_load_numeric failed") ; + } + printf ("\nDone loading numeric object\n") ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_di_solve (UMFPACK_At, Cp, Ci, Cx, x, b, + Numeric, Control, Info) ; + umfpack_di_report_info (Control, Info) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_solve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b again, using umfpack_di_wsolve instead */ + /* ---------------------------------------------------------------------- */ + + printf ("\nSolving C'x=b again, using umfpack_di_wsolve instead:\n") ; + Wi = (int *) malloc (n * sizeof (int)) ; + W = (double *) malloc (5*n * sizeof (double)) ; + if (!Wi || !W) + { + error ("out of memory") ; + } + + status = umfpack_di_wsolve (UMFPACK_At, Cp, Ci, Cx, x, b, + Numeric, Control, Info, Wi, W) ; + umfpack_di_report_info (Control, Info) ; + if (status < 0) + { + umfpack_di_report_status (Control, status) ; + error ("umfpack_di_wsolve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_di_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free everything */ + /* ---------------------------------------------------------------------- */ + + /* This is not strictly required since the process is exiting and the */ + /* system will reclaim the memory anyway. It's useful, though, just as */ + /* a list of what is currently malloc'ed by this program. Plus, it's */ + /* always a good habit to explicitly free whatever you malloc. */ + + free (Ap) ; + free (Ai) ; + free (Ax) ; + + free (Cp) ; + free (Ci) ; + free (Cx) ; + + free (Pinit) ; + free (Qinit) ; + free (Front_npivcol) ; + free (Front_1strow) ; + free (Front_leftmostdesc) ; + free (Front_parent) ; + free (Chain_start) ; + free (Chain_maxrows) ; + free (Chain_maxcols) ; + + free (Lp) ; + free (Lj) ; + free (Lx) ; + + free (Up) ; + free (Ui) ; + free (Ux) ; + + free (P) ; + free (Q) ; + + free (Li) ; + + free (Wi) ; + free (W) ; + + umfpack_di_free_symbolic (&Symbolic) ; + umfpack_di_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* print the total time spent in this demo */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (t) ; + printf ("\numfpack_di_demo complete.\nTotal time: %5.2f seconds" + " (CPU time), %5.2f seconds (wallclock time)\n", t [1], t [0]) ; + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.out b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.out @@ -0,0 +1,1541 @@ + +UMFPACK V4.4 (Jan. 28, 2005) demo: _di_ version + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: http://www.cise.ufl.edu/research/sparse/umfpack + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: int + + 0: print level: 5 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + + +b: dense vector, n = 5. + 0 : (8) + 1 : (45) + 2 : (-3) + 3 : (3) + 4 : (19) + dense vector OK + + +A: triplet-form matrix, n_row = 5, n_col = 5 nz = 12. + 0 : 0 0 (2) + 1 : 4 4 (1) + 2 : 1 0 (3) + 3 : 1 2 (4) + 4 : 2 1 (-1) + 5 : 2 2 (-3) + 6 : 0 1 (3) + 7 : 1 4 (6) + 8 : 2 3 (2) + 9 : 3 2 (1) + 10 : 4 1 (4) + 11 : 4 2 (2) + triplet-form matrix OK + + +A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (3) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3) + row 2 : (-1) + row 4 : (4) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4) + row 2 : (-3) + row 3 : (1) + row 4 : (2) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (6) + row 4 : (1) + column-form matrix OK + + +Symbolic factorization of A: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 74 (MBytes): 0.0 + estimated peak size (Units): 1301 (MBytes): 0.0 + estimated final size (Units): 15 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Numeric factorization of A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 80 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.42857e-01 + max abs. value on diagonal of U: 2.19231e+00 + reciprocal condition number estimate: 6.52e-02 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.2) + 1 : (0.0769231) + 2 : (0.166667) + 3 : (1) + 4 : (0.142857) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.307692) + row 3 : (0.285714) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.576923) + + column 3: length 1. + row 4 : (3.23077) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.571429) + + row 2: length 1. + col 4 : (0.6) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.5) + col 4 : (-0.166667) + + +diagonal of U: dense vector, n = 5. + 0 : (0.333333) + 1 : (1) + 2 : (0.4) + 3 : (0.142857) + 4 : (-2.19231) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.43e-01 + max abs. value on diagonal of U: 2.19e+00 + estimate of reciprocal of condition number: 6.52e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.19000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 4.67e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.25000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +x (solution of Ax=b): dense vector, n = 5. + 0 : (1) + 1 : (2) + 2 : (3) + 3 : (4) + 4 : (5) + dense vector OK + +maxnorm of residual: 1.77636e-15 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + +determinant: (1.14) * 10^(2) + +x (solution of Ax=b, solve is split into 3 steps): dense vector, n = 5. + 0 : (1) + 1 : (2) + 2 : (3) + 3 : (4) + 4 : (5) + dense vector OK + +maxnorm of residual: 1.77636e-15 + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.43e-01 + max abs. value on diagonal of U: 2.19e+00 + estimate of reciprocal of condition number: 6.52e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 5.84e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of A'x=b): dense vector, n = 5. + 0 : (1.81579) + 1 : (1.45614) + 2 : (1.5) + 3 : (-24.8509) + 4 : (10.2632) + dense vector OK + +maxnorm of residual: 7.10543e-15 + + +changing A (1,4) to zero + +modified A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (3) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3) + row 2 : (-1) + row 4 : (4) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4) + row 2 : (-3) + row 3 : (1) + row 4 : (2) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (0) + row 4 : (1) + column-form matrix OK + + +Numeric factorization of modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 7.00000e+00 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 79 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 3 + number of entries stored in U (excl diag): 1 + factorization floating-point operations: 4 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.50000e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.50e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.2) + 1 : (0.142857) + 2 : (0.166667) + 3 : (1) + 4 : (0.142857) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 1 + 3 : 4 + 4 : 0 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 2 : (0.571429) + row 3 : (0.285714) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.933333) + + column 3: length 1. + row 4 : (1.05) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.142857) + + row 2: length 0. End of Uchain. + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.5) + col 3 : (-0.166667) + + +diagonal of U: dense vector, n = 5. + 0 : (0.333333) + 1 : (1) + 2 : (0.428571) + 3 : (0.571429) + 4 : (-0.15) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 7.00000e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 12 80% + Numeric final size (Units) 85 80 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 4.00000e+00 31% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 8 80% + nz in L+U (incl diagonal) 15 12 80% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 8 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.50e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.50e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 8 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.17000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 5.92e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.21000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with modified A): dense vector, n = 5. + 0 : (11) + 1 : (-4.66667) + 2 : (3) + 3 : (0.666667) + 4 : (31.6667) + dense vector OK + +maxnorm of residual: 5.32907e-15 + +changing A (0,0) from 2 to 2 +changing A (1,0) from 3 to 2 +changing A (0,1) from 3 to 13 +changing A (2,1) from -1 to 7 +changing A (4,1) from 4 to 10 +changing A (1,2) from 4 to 23 +changing A (2,2) from -3 to 15 +changing A (3,2) from 1 to 18 +changing A (4,2) from 2 to 18 +changing A (2,3) from 2 to 30 +changing A (1,4) from 0 to 39 +changing A (4,4) from 1 to 37 + +completely modified A (same pattern): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (2) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (13) + row 2 : (7) + row 4 : (10) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (23) + row 2 : (15) + row 3 : (18) + row 4 : (18) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (30) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (39) + row 4 : (37) + column-form matrix OK + + +Saving symbolic object: + +Freeing symbolic object: + +Loading symbolic object: + +Done loading symbolic object + +Numeric factorization of completely modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.50000e+01 + maximum sum (abs (rows of A)): 6.50000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 80 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.33333e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.33e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.0666667) + 1 : (0.015625) + 2 : (0.0192308) + 3 : (0.0555556) + 4 : (0.0153846) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.359375) + row 3 : (0.276923) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.234375) + + column 3: length 1. + row 4 : (1.07052) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.153846) + + row 2: length 1. + col 4 : (0.866667) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (0.288462) + col 4 : (0.134615) + + +diagonal of U: dense vector, n = 5. + 0 : (0.576923) + 1 : (1) + 2 : (0.133333) + 3 : (0.569231) + 4 : (-0.367821) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.50000e+01 + maximum sum (abs (rows of A)): 6.50000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.33e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.33e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.19000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 3.70e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.25000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with completely modified A): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 3.33067e-15 + + +C (transpose of A): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (13) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (2) + row 2 : (23) + row 4 : (39) + + column 2: start: 5 end: 7 entries: 3 + row 1 : (7) + row 2 : (15) + row 3 : (30) + + column 3: start: 8 end: 8 entries: 1 + row 2 : (18) + + column 4: start: 9 end: 11 entries: 3 + row 1 : (10) + row 2 : (18) + row 4 : (37) + column-form matrix OK + + +Symbolic factorization of C: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 75 (MBytes): 0.0 + estimated peak size (Units): 1302 (MBytes): 0.0 + estimated final size (Units): 16 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Get the contents of the Symbolic object for C: +(compare with umfpack_di_report_symbolic output, above) +From the Symbolic object, C is of dimension 5-by-5 + with nz = 12, number of fronts = 1, + number of frontal matrix chains = 1 + +Pivot columns in each front, and parent of each front: + Front 0: parent front: -1 number of pivot cols: 3 + 0-th pivot column is column 3 in original matrix + 1-th pivot column is column 2 in original matrix + 2-th pivot column is column 0 in original matrix + +Note that the column ordering, above, will be refined +in the numeric factorization below. The assignment of pivot +columns to frontal matrices will always remain unchanged. + +Total number of pivot columns in frontal matrices: 3 + +Frontal matrix chains: + Frontal matrices 0 to 0 are factorized in a single + working array of size 3-by-3 + +Numeric factorization of C: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 81 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1293 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 5 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43243e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 2.43e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.25) + 1 : (0.0333333) + 2 : (0.0135135) + 3 : (0.0333333) + 4 : (0.0131579) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 1. + row 4 : (0.233333) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.866667) + + column 3: length 1. + row 4 : (0.684685) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.513158) + + row 2: length 1. + col 4 : (0.5) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 3. + col 1 : (0.202703) + col 3 : (0.243243) + col 4 : (0.310811) + + +diagonal of U: dense vector, n = 5. + 0 : (0.243243) + 1 : (1) + 2 : (0.5) + 3 : (0.486842) + 4 : (-0.784685) + dense vector OK + + Numeric object: OK + + +L (lower triangular factor of C): row-form matrix, n_row 5 n_col 5, nz = 8. + + row 0: start: 0 end: 0 entries: 1 + column 0 : (1) + + row 1: start: 1 end: 1 entries: 1 + column 1 : (1) + + row 2: start: 2 end: 2 entries: 1 + column 2 : (1) + + row 3: start: 3 end: 3 entries: 1 + column 3 : (1) + + row 4: start: 4 end: 7 entries: 4 + column 1 : (0.233333) + column 2 : (0.866667) + column 3 : (0.684685) + column 4 : (1) + row-form matrix OK + + +U (upper triangular factor of C): column-form matrix, n_row 5 n_col 5, nz = 10. + + column 0: start: 0 end: 0 entries: 1 + row 0 : (0.243243) + + column 1: start: 1 end: 2 entries: 2 + row 0 : (0.202703) + row 1 : (1) + + column 2: start: 3 end: 3 entries: 1 + row 2 : (0.5) + + column 3: start: 4 end: 5 entries: 2 + row 0 : (0.243243) + row 3 : (0.486842) + + column 4: start: 6 end: 9 entries: 4 + row 0 : (0.310811) + row 2 : (0.5) + row 3 : (0.513158) + row 4 : (-0.784685) + column-form matrix OK + + +P: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Scale factors: row i of A is to be multiplied by the ith scale factor +0: 0.25 +1: 0.0333333 +2: 0.0135135 +3: 0.0333333 +4: 0.0131579 + +Converting L to triplet form, and printing it: + +L, in triplet form: triplet-form matrix, n_row = 5, n_col = 5 nz = 8. + 0 : 0 0 (1) + 1 : 1 1 (1) + 2 : 2 2 (1) + 3 : 3 3 (1) + 4 : 4 1 (0.233333) + 5 : 4 2 (0.866667) + 6 : 4 3 (0.684685) + 7 : 4 4 (1) + triplet-form matrix OK + + +Saving numeric object: + +Freeing numeric object: + +Loading numeric object: + +Done loading numeric object + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 75 70 93% + peak size (Units) 1302 1293 99% + final size (Units) 16 14 88% + Numeric final size (Units) 86 82 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1474 1465 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.43e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.60e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 4.77396e-15 + + +Solving C'x=b again, using umfpack_di_wsolve instead: + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 75 70 93% + peak size (Units) 1302 1293 99% + final size (Units) 16 14 88% + Numeric final size (Units) 86 82 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1474 1465 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.43e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.60e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 4.77396e-15 + + +umfpack_di_demo complete. +Total time: 0.00 seconds (CPU time), 0.00 seconds (wallclock time) diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.sed b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.sed new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_di_demo.sed @@ -0,0 +1,78 @@ +/::/d +1,$s/_xx_/_di_/g +1,$s/Int/int/g +1,$s/WSIZE/5/ +1,$s/%ld/%d/g +/define ABS/ { + s/ABS/ABS(x) ((x) >= 0 ? (x) : -(x))/ + } +/, rz \[i\]/ { + s/, rz \[i\]// + } +/, Avalz/ { + s/, Avalz// + } +/, rz/ { + s/, rz// + } +/, bz/ { + s/, bz// + } +/, xz/ { + s/, xz// + } + +/, Lz/ { + s/, Lz// + } +/, Uz/ { + s/, Uz// + } +/, Dz/ { + s/, Dz// + } +/, Az/ { + s/, Az// + } +/, Cz, TRUE/ { + s/, Cz, TRUE// + } +/, Cz/ { + s/, Cz// + } +/, Rbz/ { + s/, Rbz// + } +/, yz/ { + s/, yz// + } + +/ || !Lz/ { + s/ || !Lz// + } +/ || !Uz/ { + s/ || !Uz// + } +/ || !Dz/ { + s/ || !Dz// + } +/ || !Az/ { + s/ || !Az// + } +/ || !Cz/ { + s/ || !Cz// + } + +/rz/d +/Rbz/d +/yz/d +/Avalz/d +/Az/d +/Cz/d +/bz/d +/xz/d +/Lz/d +/Uz/d +/Dz/d +/complex/d + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.c @@ -0,0 +1,759 @@ +/* ========================================================================== */ +/* === umfpack_dl_demo ====================================================== */ +/* ========================================================================== */ + + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + A demo of UMFPACK: umfpack_dl_* version. + + First, factor and solve a 5-by-5 system, Ax=b, using default parameters. + Then solve A'x=b using the factors of A. Modify one entry (A (1,4) = 0, + where the row and column indices range from 0 to 4. The pattern of A + has not changed (it has explicitly zero entry), so a reanalysis with + umfpack_dl_symbolic does not need to be done. Refactorize (with + umfpack_dl_numeric), and solve Ax=b. Note that the pivot ordering has + changed. Next, change all of the entries in A, but not the pattern. + + Finally, compute C = A', and do the symbolic and numeric factorization of C. + Factorizing A' can sometimes be better than factorizing A itself (less work + and memory usage). Solve C'x=b twice; the solution is the same as the + solution to Ax=b. + + A note about zero-sized arrays: UMFPACK uses many user-provided arrays of + size n (order of the matrix), and of size nz (the number of nonzeros in a + matrix). n cannot be zero; UMFPACK does not handle zero-dimensioned arrays. + However, nz can be zero. If you attempt to malloc an array of size nz = 0, + however, malloc will return a null pointer which UMFPACK will report as a + "missing argument." Thus, nz1 in this code is set to MAX (nz,1), and + similarly for lnz and unz. Lnz can never be zero, however, since L is always + unit diagonal. +*/ + +/* -------------------------------------------------------------------------- */ +/* definitions */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "umfpack.h" + +#define ABS(x) ((x) >= 0 ? (x) : -(x)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ +/* triplet form of the matrix. The triplets can be in any order. */ +/* -------------------------------------------------------------------------- */ + +static long n = 5, nz = 12 ; +static long Arow [ ] = { 0, 4, 1, 1, 2, 2, 0, 1, 2, 3, 4, 4} ; +static long Acol [ ] = { 0, 4, 0, 2, 1, 2, 1, 4, 3, 2, 1, 2} ; +static double Aval [ ] = {2., 1., 3., 4., -1., -3., 3., 6., 2., 1., 4., 2.} ; +static double b [ ] = {8., 45., -3., 3., 19.}, x [5], r [5] ; + + +/* -------------------------------------------------------------------------- */ +/* error: print a message and exit */ +/* -------------------------------------------------------------------------- */ + +static void error +( + char *message +) +{ + printf ("\n\n====== error: %s =====\n\n", message) ; + exit (1) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the residual, r = Ax-b or r = A'x=b and return maxnorm (r) */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + long transpose, + long Ap [ ], + long Ai [ ], + double Ax [ ] +) +{ + long i, j, p ; + double norm ; + + for (i = 0 ; i < n ; i++) + { + r [i] = -b [i] ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [j] += Ax [p] * x [i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + } + } + } + norm = 0. ; + for (i = 0 ; i < n ; i++) + { + norm = MAX (ABS (r [i]), norm) ; + } + return (norm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], *Ax, *Cx, *Lx, *Ux, + *W, t [2], *Dx, rnorm, *Rb, *y, *Rs ; + long *Ap, *Ai, *Cp, *Ci, row, col, p, lnz, unz, nr, nc, *Lp, *Li, *Ui, *Up, + *P, *Q, *Lj, i, j, k, anz, nfr, nchains, *Qinit, fnpiv, lnz1, unz1, nz1, + status, *Front_npivcol, *Front_parent, *Chain_start, *Wi, *Pinit, n1, + *Chain_maxrows, *Chain_maxcols, *Front_1strow, *Front_leftmostdesc, + nzud, do_recip ; + void *Symbolic, *Numeric ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (t) ; + + printf ("\n%s demo: _dl_ version\n", UMFPACK_VERSION) ; + + /* get the default control parameters */ + umfpack_dl_defaults (Control) ; + + /* change the default print level for this demo */ + /* (otherwise, nothing will print) */ + Control [UMFPACK_PRL] = 6 ; + + /* print the license agreement */ + umfpack_dl_report_status (Control, UMFPACK_OK) ; + Control [UMFPACK_PRL] = 5 ; + + /* print the control parameters */ + umfpack_dl_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* print A and b, and convert A to column-form */ + /* ---------------------------------------------------------------------- */ + + /* print the right-hand-side */ + printf ("\nb: ") ; + (void) umfpack_dl_report_vector (n, b, Control) ; + + /* print the triplet form of the matrix */ + printf ("\nA: ") ; + (void) umfpack_dl_report_triplet (n, n, nz, Arow, Acol, Aval, + Control) ; + + /* convert to column form */ + nz1 = MAX (nz,1) ; /* ensure arrays are not of size zero. */ + Ap = (long *) malloc ((n+1) * sizeof (long)) ; + Ai = (long *) malloc (nz1 * sizeof (long)) ; + Ax = (double *) malloc (nz1 * sizeof (double)) ; + if (!Ap || !Ai || !Ax) + { + error ("out of memory") ; + } + + status = umfpack_dl_triplet_to_col (n, n, nz, Arow, Acol, Aval, + Ap, Ai, Ax, (long *) NULL) ; + + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_triplet_to_col failed") ; + } + + /* print the column-form of A */ + printf ("\nA: ") ; + (void) umfpack_dl_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_symbolic (n, n, Ap, Ai, Ax, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_symbolic failed") ; + } + + /* print the symbolic factorization */ + + printf ("\nSymbolic factorization of A: ") ; + (void) umfpack_dl_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_numeric failed") ; + } + + /* print the numeric factorization */ + printf ("\nNumeric factorization of A: ") ; + (void) umfpack_dl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_dl_solve failed") ; + } + printf ("\nx (solution of Ax=b): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_get_determinant (x, r, Numeric, Info) ; + umfpack_dl_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_dl_get_determinant failed") ; + } + printf ("determinant: (%g", x [0]) ; + printf (") * 10^(%g)\n", r [0]) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, broken down into steps */ + /* ---------------------------------------------------------------------- */ + + /* Rb = R*b */ + Rb = (double *) malloc (n * sizeof (double)) ; + y = (double *) malloc (n * sizeof (double)) ; + if (!Rb || !y) error ("out of memory") ; + + status = umfpack_dl_scale (Rb, b, Numeric) ; + if (status < 0) error ("umfpack_dl_scale failed") ; + /* solve Ly = P*(Rb) */ + status = umfpack_dl_solve (UMFPACK_Pt_L, Ap, Ai, Ax, y, Rb, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_dl_solve failed") ; + /* solve UQ'x=y */ + status = umfpack_dl_solve (UMFPACK_U_Qt, Ap, Ai, Ax, x, y, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_dl_solve failed") ; + printf ("\nx (solution of Ax=b, solve is split into 3 steps): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + free (Rb) ; + free (y) ; + + /* ---------------------------------------------------------------------- */ + /* solve A'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_solve (UMFPACK_At, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_dl_report_info (Control, Info) ; + if (status < 0) + { + error ("umfpack_dl_solve failed") ; + } + printf ("\nx (solution of A'x=b): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify one numerical value in the column-form of A */ + /* ---------------------------------------------------------------------- */ + + /* change A (1,4), look for row index 1 in column 4. */ + row = 1 ; + col = 4 ; + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + if (row == Ai [p]) + { + printf ("\nchanging A (%ld,%ld) to zero\n", row, col) ; + Ax [p] = 0.0 ; + break ; + } + } + printf ("\nmodified A: ") ; + (void) umfpack_dl_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* The pattern (Ap and Ai) hasn't changed, so the symbolic factorization */ + /* doesn't have to be redone, no matter how much we change Ax. */ + + /* We don't need the Numeric object any more, so free it. */ + umfpack_dl_free_numeric (&Numeric) ; + + /* Note that a memory leak would have occurred if the old Numeric */ + /* had not been free'd with umfpack_dl_free_numeric above. */ + status = umfpack_dl_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_numeric failed") ; + } + printf ("\nNumeric factorization of modified A: ") ; + (void) umfpack_dl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_dl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_solve failed") ; + } + printf ("\nx (with modified A): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify all of the numerical values of A, but not the pattern */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < n ; col++) + { + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + row = Ai [p] ; + printf ("changing ") ; + printf ("A (%ld,%ld) from %g", row, col, Ax [p]) ; + Ax [p] = Ax [p] + col*10 - row ; + printf (" to %g\n", Ax [p]) ; + } + } + printf ("\ncompletely modified A (same pattern): ") ; + (void) umfpack_dl_report_matrix (n, n, Ap, Ai, Ax, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Symbolic object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "symbolic.umf" */ + printf ("\nSaving symbolic object:\n") ; + status = umfpack_dl_save_symbolic (Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_save_symbolic failed") ; + } + printf ("\nFreeing symbolic object:\n") ; + umfpack_dl_free_symbolic (&Symbolic) ; + printf ("\nLoading symbolic object:\n") ; + status = umfpack_dl_load_symbolic (&Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_load_symbolic failed") ; + } + printf ("\nDone loading symbolic object\n") ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_dl_free_numeric (&Numeric) ; + status = umfpack_dl_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_numeric failed") ; + } + printf ("\nNumeric factorization of completely modified A: ") ; + (void) umfpack_dl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_solve (UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, Control, Info) ; + umfpack_dl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_solve failed") ; + } + printf ("\nx (with completely modified A): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free the symbolic and numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_dl_free_symbolic (&Symbolic) ; + umfpack_dl_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* C = transpose of A */ + /* ---------------------------------------------------------------------- */ + + Cp = (long *) malloc ((n+1) * sizeof (long)) ; + Ci = (long *) malloc (nz1 * sizeof (long)) ; + Cx = (double *) malloc (nz1 * sizeof (double)) ; + if (!Cp || !Ci || !Cx) + { + error ("out of memory") ; + } + status = umfpack_dl_transpose (n, n, Ap, Ai, Ax, + (long *) NULL, (long *) NULL, Cp, Ci, Cx) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_transpose failed: ") ; + } + printf ("\nC (transpose of A): ") ; + (void) umfpack_dl_report_matrix (n, n, Cp, Ci, Cx, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_symbolic (n, n, Cp, Ci, Cx, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_dl_report_info (Control, Info) ; + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_symbolic failed") ; + } + printf ("\nSymbolic factorization of C: ") ; + (void) umfpack_dl_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* copy the contents of Symbolic into user arrays print them */ + /* ---------------------------------------------------------------------- */ + + printf ("\nGet the contents of the Symbolic object for C:\n") ; + printf ("(compare with umfpack_dl_report_symbolic output, above)\n") ; + Pinit = (long *) malloc ((n+1) * sizeof (long)) ; + Qinit = (long *) malloc ((n+1) * sizeof (long)) ; + Front_npivcol = (long *) malloc ((n+1) * sizeof (long)) ; + Front_1strow = (long *) malloc ((n+1) * sizeof (long)) ; + Front_leftmostdesc = (long *) malloc ((n+1) * sizeof (long)) ; + Front_parent = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_start = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_maxrows = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_maxcols = (long *) malloc ((n+1) * sizeof (long)) ; + if (!Pinit || !Qinit || !Front_npivcol || !Front_parent || !Chain_start || + !Chain_maxrows || !Chain_maxcols || !Front_1strow || + !Front_leftmostdesc) + { + error ("out of memory") ; + } + + status = umfpack_dl_get_symbolic (&nr, &nc, &n1, &anz, &nfr, &nchains, + Pinit, Qinit, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + + if (status < 0) + { + error ("symbolic factorization invalid") ; + } + + printf ("From the Symbolic object, C is of dimension %ld-by-%ld\n", nr, nc); + printf (" with nz = %ld, number of fronts = %ld,\n", nz, nfr) ; + printf (" number of frontal matrix chains = %ld\n", nchains) ; + + printf ("\nPivot columns in each front, and parent of each front:\n") ; + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fnpiv = Front_npivcol [i] ; + printf (" Front %ld: parent front: %ld number of pivot cols: %ld\n", + i, Front_parent [i], fnpiv) ; + for (j = 0 ; j < fnpiv ; j++) + { + col = Qinit [k] ; + printf ( + " %ld-th pivot column is column %ld in original matrix\n", + k, col) ; + k++ ; + } + } + + printf ("\nNote that the column ordering, above, will be refined\n") ; + printf ("in the numeric factorization below. The assignment of pivot\n") ; + printf ("columns to frontal matrices will always remain unchanged.\n") ; + + printf ("\nTotal number of pivot columns in frontal matrices: %ld\n", k) ; + + printf ("\nFrontal matrix chains:\n") ; + for (j = 0 ; j < nchains ; j++) + { + printf (" Frontal matrices %ld to %ld are factorized in a single\n", + Chain_start [j], Chain_start [j+1] - 1) ; + printf (" working array of size %ld-by-%ld\n", + Chain_maxrows [j], Chain_maxcols [j]) ; + } + + /* ---------------------------------------------------------------------- */ + /* numeric factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_numeric (Cp, Ci, Cx, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + error ("umfpack_dl_numeric failed") ; + } + printf ("\nNumeric factorization of C: ") ; + (void) umfpack_dl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* extract the LU factors of C and print them */ + /* ---------------------------------------------------------------------- */ + + if (umfpack_dl_get_lunz (&lnz, &unz, &nr, &nc, &nzud, Numeric) < 0) + { + error ("umfpack_dl_get_lunz failed") ; + } + /* ensure arrays are not of zero size */ + lnz1 = MAX (lnz,1) ; + unz1 = MAX (unz,1) ; + Lp = (long *) malloc ((n+1) * sizeof (long)) ; + Lj = (long *) malloc (lnz1 * sizeof (long)) ; + Lx = (double *) malloc (lnz1 * sizeof (double)) ; + Up = (long *) malloc ((n+1) * sizeof (long)) ; + Ui = (long *) malloc (unz1 * sizeof (long)) ; + Ux = (double *) malloc (unz1 * sizeof (double)) ; + P = (long *) malloc (n * sizeof (long)) ; + Q = (long *) malloc (n * sizeof (long)) ; + Dx = (double *) NULL ; /* D vector not requested */ + Rs = (double *) malloc (n * sizeof (double)) ; + if (!Lp || !Lj || !Lx || !Up || !Ui || !Ux || !P || !Q || !Rs) + { + error ("out of memory") ; + } + status = umfpack_dl_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, + P, Q, Dx, &do_recip, Rs, Numeric) ; + if (status < 0) + { + error ("umfpack_dl_get_numeric failed") ; + } + + printf ("\nL (lower triangular factor of C): ") ; + (void) umfpack_dl_report_matrix (n, n, Lp, Lj, Lx, 0, Control) ; + printf ("\nU (upper triangular factor of C): ") ; + (void) umfpack_dl_report_matrix (n, n, Up, Ui, Ux, 1, Control) ; + printf ("\nP: ") ; + (void) umfpack_dl_report_perm (n, P, Control) ; + printf ("\nQ: ") ; + (void) umfpack_dl_report_perm (n, Q, Control) ; + printf ("\nScale factors: row i of A is to be ") ; + if (do_recip) + { + printf ("multiplied by the ith scale factor\n") ; + } + else + { + printf ("divided by the ith scale factor\n") ; + } + for (i = 0 ; i < n ; i++) printf ("%ld: %g\n", i, Rs [i]) ; + + /* ---------------------------------------------------------------------- */ + /* convert L to triplet form and print it */ + /* ---------------------------------------------------------------------- */ + + /* Note that L is in row-form, so it is the row indices that are created */ + /* by umfpack_dl_col_to_triplet. */ + + printf ("\nConverting L to triplet form, and printing it:\n") ; + Li = (long *) malloc (lnz1 * sizeof (long)) ; + if (!Li) + { + error ("out of memory") ; + } + if (umfpack_dl_col_to_triplet (n, Lp, Li) < 0) + { + error ("umfpack_dl_col_to_triplet failed") ; + } + printf ("\nL, in triplet form: ") ; + (void) umfpack_dl_report_triplet (n, n, lnz, Li, Lj, Lx, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Numeric object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "numeric.umf" */ + printf ("\nSaving numeric object:\n") ; + status = umfpack_dl_save_numeric (Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_save_numeric failed") ; + } + printf ("\nFreeing numeric object:\n") ; + umfpack_dl_free_numeric (&Numeric) ; + printf ("\nLoading numeric object:\n") ; + status = umfpack_dl_load_numeric (&Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_load_numeric failed") ; + } + printf ("\nDone loading numeric object\n") ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_dl_solve (UMFPACK_At, Cp, Ci, Cx, x, b, + Numeric, Control, Info) ; + umfpack_dl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_solve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b again, using umfpack_dl_wsolve instead */ + /* ---------------------------------------------------------------------- */ + + printf ("\nSolving C'x=b again, using umfpack_dl_wsolve instead:\n") ; + Wi = (long *) malloc (n * sizeof (long)) ; + W = (double *) malloc (5*n * sizeof (double)) ; + if (!Wi || !W) + { + error ("out of memory") ; + } + + status = umfpack_dl_wsolve (UMFPACK_At, Cp, Ci, Cx, x, b, + Numeric, Control, Info, Wi, W) ; + umfpack_dl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_dl_report_status (Control, status) ; + error ("umfpack_dl_wsolve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_dl_report_vector (n, x, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free everything */ + /* ---------------------------------------------------------------------- */ + + /* This is not strictly required since the process is exiting and the */ + /* system will reclaim the memory anyway. It's useful, though, just as */ + /* a list of what is currently malloc'ed by this program. Plus, it's */ + /* always a good habit to explicitly free whatever you malloc. */ + + free (Ap) ; + free (Ai) ; + free (Ax) ; + + free (Cp) ; + free (Ci) ; + free (Cx) ; + + free (Pinit) ; + free (Qinit) ; + free (Front_npivcol) ; + free (Front_1strow) ; + free (Front_leftmostdesc) ; + free (Front_parent) ; + free (Chain_start) ; + free (Chain_maxrows) ; + free (Chain_maxcols) ; + + free (Lp) ; + free (Lj) ; + free (Lx) ; + + free (Up) ; + free (Ui) ; + free (Ux) ; + + free (P) ; + free (Q) ; + + free (Li) ; + + free (Wi) ; + free (W) ; + + umfpack_dl_free_symbolic (&Symbolic) ; + umfpack_dl_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* print the total time spent in this demo */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (t) ; + printf ("\numfpack_dl_demo complete.\nTotal time: %5.2f seconds" + " (CPU time), %5.2f seconds (wallclock time)\n", t [1], t [0]) ; + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.out b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.out @@ -0,0 +1,1541 @@ + +UMFPACK V4.4 (Jan. 28, 2005) demo: _dl_ version + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: http://www.cise.ufl.edu/research/sparse/umfpack + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double + Int (generic integer) defined as: long + + 0: print level: 5 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 8 (in bytes) + + +b: dense vector, n = 5. + 0 : (8) + 1 : (45) + 2 : (-3) + 3 : (3) + 4 : (19) + dense vector OK + + +A: triplet-form matrix, n_row = 5, n_col = 5 nz = 12. + 0 : 0 0 (2) + 1 : 4 4 (1) + 2 : 1 0 (3) + 3 : 1 2 (4) + 4 : 2 1 (-1) + 5 : 2 2 (-3) + 6 : 0 1 (3) + 7 : 1 4 (6) + 8 : 2 3 (2) + 9 : 3 2 (1) + 10 : 4 1 (4) + 11 : 4 2 (2) + triplet-form matrix OK + + +A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (3) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3) + row 2 : (-1) + row 4 : (4) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4) + row 2 : (-3) + row 3 : (1) + row 4 : (2) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (6) + row 4 : (1) + column-form matrix OK + + +Symbolic factorization of A: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 74 (MBytes): 0.0 + estimated peak size (Units): 1301 (MBytes): 0.0 + estimated final size (Units): 15 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Numeric factorization of A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 80 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.42857e-01 + max abs. value on diagonal of U: 2.19231e+00 + reciprocal condition number estimate: 6.52e-02 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.2) + 1 : (0.0769231) + 2 : (0.166667) + 3 : (1) + 4 : (0.142857) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.307692) + row 3 : (0.285714) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.576923) + + column 3: length 1. + row 4 : (3.23077) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.571429) + + row 2: length 1. + col 4 : (0.6) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.5) + col 4 : (-0.166667) + + +diagonal of U: dense vector, n = 5. + 0 : (0.333333) + 1 : (1) + 2 : (0.4) + 3 : (0.142857) + 4 : (-2.19231) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.43e-01 + max abs. value on diagonal of U: 2.19e+00 + estimate of reciprocal of condition number: 6.52e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.19000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 4.67e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.25000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +x (solution of Ax=b): dense vector, n = 5. + 0 : (1) + 1 : (2) + 2 : (3) + 3 : (4) + 4 : (5) + dense vector OK + +maxnorm of residual: 1.77636e-15 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + +determinant: (1.14) * 10^(2) + +x (solution of Ax=b, solve is split into 3 steps): dense vector, n = 5. + 0 : (1) + 1 : (2) + 2 : (3) + 3 : (4) + 4 : (5) + dense vector OK + +maxnorm of residual: 1.77636e-15 + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.30000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.43e-01 + max abs. value on diagonal of U: 2.19e+00 + estimate of reciprocal of condition number: 6.52e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 5.84e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of A'x=b): dense vector, n = 5. + 0 : (1.81579) + 1 : (1.45614) + 2 : (1.5) + 3 : (-24.8509) + 4 : (10.2632) + dense vector OK + +maxnorm of residual: 7.10543e-15 + + +changing A (1,4) to zero + +modified A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (3) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3) + row 2 : (-1) + row 4 : (4) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4) + row 2 : (-3) + row 3 : (1) + row 4 : (2) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (0) + row 4 : (1) + column-form matrix OK + + +Numeric factorization of modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 7.00000e+00 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 79 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 3 + number of entries stored in U (excl diag): 1 + factorization floating-point operations: 4 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.50000e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.50e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.2) + 1 : (0.142857) + 2 : (0.166667) + 3 : (1) + 4 : (0.142857) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 1 + 3 : 4 + 4 : 0 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 2 : (0.571429) + row 3 : (0.285714) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.933333) + + column 3: length 1. + row 4 : (1.05) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.142857) + + row 2: length 0. End of Uchain. + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.5) + col 3 : (-0.166667) + + +diagonal of U: dense vector, n = 5. + 0 : (0.333333) + 1 : (1) + 2 : (0.428571) + 3 : (0.571429) + 4 : (-0.15) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 7.00000e+00 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 12 80% + Numeric final size (Units) 85 80 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 4.00000e+00 31% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 8 80% + nz in L+U (incl diagonal) 15 12 80% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 8 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.50e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.50e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 8 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.17000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 5.92e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.21000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with modified A): dense vector, n = 5. + 0 : (11) + 1 : (-4.66667) + 2 : (3) + 3 : (0.666667) + 4 : (31.6667) + dense vector OK + +maxnorm of residual: 5.32907e-15 + +changing A (0,0) from 2 to 2 +changing A (1,0) from 3 to 2 +changing A (0,1) from 3 to 13 +changing A (2,1) from -1 to 7 +changing A (4,1) from 4 to 10 +changing A (1,2) from 4 to 23 +changing A (2,2) from -3 to 15 +changing A (3,2) from 1 to 18 +changing A (4,2) from 2 to 18 +changing A (2,3) from 2 to 30 +changing A (1,4) from 0 to 39 +changing A (4,4) from 1 to 37 + +completely modified A (same pattern): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (2) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (13) + row 2 : (7) + row 4 : (10) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (23) + row 2 : (15) + row 3 : (18) + row 4 : (18) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (30) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (39) + row 4 : (37) + column-form matrix OK + + +Saving symbolic object: + +Freeing symbolic object: + +Loading symbolic object: + +Done loading symbolic object + +Numeric factorization of completely modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.50000e+01 + maximum sum (abs (rows of A)): 6.50000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 80 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1292 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.33333e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.33e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.0666667) + 1 : (0.015625) + 2 : (0.0192308) + 3 : (0.0555556) + 4 : (0.0153846) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.359375) + row 3 : (0.276923) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.234375) + + column 3: length 1. + row 4 : (1.07052) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.153846) + + row 2: length 1. + col 4 : (0.866667) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (0.288462) + col 4 : (0.134615) + + +diagonal of U: dense vector, n = 5. + 0 : (0.576923) + 1 : (1) + 2 : (0.133333) + 3 : (0.569231) + 4 : (-0.367821) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.50000e+01 + maximum sum (abs (rows of A)): 6.50000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 74 69 93% + peak size (Units) 1301 1292 99% + final size (Units) 15 13 87% + Numeric final size (Units) 85 81 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1473 1464 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.33e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.33e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.19000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 3.70e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.25000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with completely modified A): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 3.33067e-15 + + +C (transpose of A): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2) + row 1 : (13) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (2) + row 2 : (23) + row 4 : (39) + + column 2: start: 5 end: 7 entries: 3 + row 1 : (7) + row 2 : (15) + row 3 : (30) + + column 3: start: 8 end: 8 entries: 1 + row 2 : (18) + + column 4: start: 9 end: 11 entries: 3 + row 1 : (10) + row 2 : (18) + row 4 : (37) + column-form matrix OK + + +Symbolic factorization of C: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 75 (MBytes): 0.0 + estimated peak size (Units): 1302 (MBytes): 0.0 + estimated final size (Units): 16 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Get the contents of the Symbolic object for C: +(compare with umfpack_dl_report_symbolic output, above) +From the Symbolic object, C is of dimension 5-by-5 + with nz = 12, number of fronts = 1, + number of frontal matrix chains = 1 + +Pivot columns in each front, and parent of each front: + Front 0: parent front: -1 number of pivot cols: 3 + 0-th pivot column is column 3 in original matrix + 1-th pivot column is column 2 in original matrix + 2-th pivot column is column 0 in original matrix + +Note that the column ordering, above, will be refined +in the numeric factorization below. The assignment of pivot +columns to frontal matrices will always remain unchanged. + +Total number of pivot columns in frontal matrices: 3 + +Frontal matrix chains: + Frontal matrices 0 to 0 are factorized in a single + working array of size 3-by-3 + +Numeric factorization of C: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 81 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 1293 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 5 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 6 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43243e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 2.43e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.25) + 1 : (0.0333333) + 2 : (0.0135135) + 3 : (0.0333333) + 4 : (0.0131579) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 1. + row 4 : (0.233333) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.866667) + + column 3: length 1. + row 4 : (0.684685) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.513158) + + row 2: length 1. + col 4 : (0.5) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 3. + col 1 : (0.202703) + col 3 : (0.243243) + col 4 : (0.310811) + + +diagonal of U: dense vector, n = 5. + 0 : (0.243243) + 1 : (1) + 2 : (0.5) + 3 : (0.486842) + 4 : (-0.784685) + dense vector OK + + Numeric object: OK + + +L (lower triangular factor of C): row-form matrix, n_row 5 n_col 5, nz = 8. + + row 0: start: 0 end: 0 entries: 1 + column 0 : (1) + + row 1: start: 1 end: 1 entries: 1 + column 1 : (1) + + row 2: start: 2 end: 2 entries: 1 + column 2 : (1) + + row 3: start: 3 end: 3 entries: 1 + column 3 : (1) + + row 4: start: 4 end: 7 entries: 4 + column 1 : (0.233333) + column 2 : (0.866667) + column 3 : (0.684685) + column 4 : (1) + row-form matrix OK + + +U (upper triangular factor of C): column-form matrix, n_row 5 n_col 5, nz = 10. + + column 0: start: 0 end: 0 entries: 1 + row 0 : (0.243243) + + column 1: start: 1 end: 2 entries: 2 + row 0 : (0.202703) + row 1 : (1) + + column 2: start: 3 end: 3 entries: 1 + row 2 : (0.5) + + column 3: start: 4 end: 5 entries: 2 + row 0 : (0.243243) + row 3 : (0.486842) + + column 4: start: 6 end: 9 entries: 4 + row 0 : (0.310811) + row 2 : (0.5) + row 3 : (0.513158) + row 4 : (-0.784685) + column-form matrix OK + + +P: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Scale factors: row i of A is to be multiplied by the ith scale factor +0: 0.25 +1: 0.0333333 +2: 0.0135135 +3: 0.0333333 +4: 0.0131579 + +Converting L to triplet form, and printing it: + +L, in triplet form: triplet-form matrix, n_row = 5, n_col = 5 nz = 8. + 0 : 0 0 (1) + 1 : 1 1 (1) + 2 : 2 2 (1) + 3 : 3 3 (1) + 4 : 4 1 (0.233333) + 5 : 4 2 (0.866667) + 6 : 4 3 (0.684685) + 7 : 4 4 (1) + triplet-form matrix OK + + +Saving numeric object: + +Freeing numeric object: + +Loading numeric object: + +Done loading numeric object + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 75 70 93% + peak size (Units) 1302 1293 99% + final size (Units) 16 14 88% + Numeric final size (Units) 86 82 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1474 1465 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.43e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.60e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 4.77396e-15 + + +Solving C'x=b again, using umfpack_dl_wsolve instead: + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 8 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 4.00000e+00 + maximum sum (abs (rows of A)): 7.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 75 70 93% + peak size (Units) 1302 1293 99% + final size (Units) 16 14 88% + Numeric final size (Units) 86 82 95% + Numeric final size (MBytes) 0.0 0.0 95% + peak memory usage (Units) 1474 1465 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 1.30000e+01 6.00000e+00 46% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.43e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 2.43e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 1.11000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.60e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 1.17000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (8.50124) + 1 : (-0.692499) + 2 : (0.166667) + 3 : (-0.0217502) + 4 : (0.619594) + dense vector OK + +maxnorm of residual: 4.77396e-15 + + +umfpack_dl_demo complete. +Total time: 0.00 seconds (CPU time), 0.00 seconds (wallclock time) diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.sed b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.sed new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_dl_demo.sed @@ -0,0 +1,77 @@ +/::/d +1,$s/_xx_/_dl_/g +1,$s/Int/long/g +1,$s/WSIZE/5/ +/define ABS/ { + s/ABS/ABS(x) ((x) >= 0 ? (x) : -(x))/ + } +/, rz \[i\]/ { + s/, rz \[i\]// + } +/, Avalz/ { + s/, Avalz// + } +/, rz/ { + s/, rz// + } +/, bz/ { + s/, bz// + } +/, xz/ { + s/, xz// + } + +/, Lz/ { + s/, Lz// + } +/, Uz/ { + s/, Uz// + } +/, Dz/ { + s/, Dz// + } +/, Az/ { + s/, Az// + } +/, Cz, TRUE/ { + s/, Cz, TRUE// + } +/, Cz/ { + s/, Cz// + } +/, Rbz/ { + s/, Rbz// + } +/, yz/ { + s/, yz// + } + +/ || !Lz/ { + s/ || !Lz// + } +/ || !Uz/ { + s/ || !Uz// + } +/ || !Dz/ { + s/ || !Dz// + } +/ || !Az/ { + s/ || !Az// + } +/ || !Cz/ { + s/ || !Cz// + } + +/rz/d +/Rbz/d +/yz/d +/Avalz/d +/Az/d +/Cz/d +/bz/d +/xz/d +/Lz/d +/Uz/d +/Dz/d +/complex/d + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_simple.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_simple.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_simple.c @@ -0,0 +1,30 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include +#include "umfpack.h" + +int n = 5 ; +int Ap [ ] = {0, 2, 5, 9, 10, 12} ; +int Ai [ ] = { 0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4} ; +double Ax [ ] = {2., 3., 3., -1., 4., 4., -3., 1., 2., 2., 6., 1.} ; +double b [ ] = {8., 45., -3., 3., 19.} ; +double x [5] ; + +int main (void) +{ + double *null = (double *) NULL ; + int i ; + void *Symbolic, *Numeric ; + (void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null) ; + (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null) ; + umfpack_di_free_symbolic (&Symbolic) ; + (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null) ; + umfpack_di_free_numeric (&Numeric) ; + for (i = 0 ; i < n ; i++) printf ("x [%d] = %g\n", i, x [i]) ; + return (0) ; +} + diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_xx_demo.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_xx_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_xx_demo.c @@ -0,0 +1,810 @@ +/* ========================================================================== */ +/* === umfpack_xx_demo ====================================================== */ +/* ========================================================================== */ + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: Do not attempt to compile this file! It is processed via sed scripts into +:: four different C demo programs: +:: +:: umfpack_di_demo.c: double precision, int integers +:: umfpack_dl_demo.c: double precision, long integers +:: umfpack_zi_demo.c: complex double precision, int integers +:: umfpack_zl_demo.c: complex double precision, long integers +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + A demo of UMFPACK: umfpack_xx_* version. + + First, factor and solve a 5-by-5 system, Ax=b, using default parameters. + Then solve A'x=b using the factors of A. Modify one entry (A (1,4) = 0, + where the row and column indices range from 0 to 4. The pattern of A + has not changed (it has explicitly zero entry), so a reanalysis with + umfpack_xx_symbolic does not need to be done. Refactorize (with + umfpack_xx_numeric), and solve Ax=b. Note that the pivot ordering has + changed. Next, change all of the entries in A, but not the pattern. + + Finally, compute C = A', and do the symbolic and numeric factorization of C. + Factorizing A' can sometimes be better than factorizing A itself (less work + and memory usage). Solve C'x=b twice; the solution is the same as the + solution to Ax=b. + + A note about zero-sized arrays: UMFPACK uses many user-provided arrays of + size n (order of the matrix), and of size nz (the number of nonzeros in a + matrix). n cannot be zero; UMFPACK does not handle zero-dimensioned arrays. + However, nz can be zero. If you attempt to malloc an array of size nz = 0, + however, malloc will return a null pointer which UMFPACK will report as a + "missing argument." Thus, nz1 in this code is set to MAX (nz,1), and + similarly for lnz and unz. Lnz can never be zero, however, since L is always + unit diagonal. +*/ + +/* -------------------------------------------------------------------------- */ +/* definitions */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "umfpack.h" + +/* use a cheap approximate absolute value for complex numbers: */ +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: ABS is |xreal|+|ximag| for the complex case, and |x| for the real case. +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +#define ABS + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ +/* triplet form of the matrix. The triplets can be in any order. */ +/* -------------------------------------------------------------------------- */ + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: Int is either int or long: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +static Int n = 5, nz = 12 ; +static Int Arow [ ] = { 0, 4, 1, 1, 2, 2, 0, 1, 2, 3, 4, 4} ; +static Int Acol [ ] = { 0, 4, 0, 2, 1, 2, 1, 4, 3, 2, 1, 2} ; +static double Aval [ ] = {2., 1., 3., 4., -1., -3., 3., 6., 2., 1., 4., 2.} ; +static double Avalz[ ] = {1., .4, .1, .2, -1., -.2, 0., 6., 3., 0., .3, .3} ; +static double b [ ] = {8., 45., -3., 3., 19.}, x [5], r [5] ; +static double bz[ ] = {1., -5., -2., 0., 2.2}, xz[5], rz[5] ; + +/* Avalz, bz: imaginary part of A and b */ + +/* -------------------------------------------------------------------------- */ +/* error: print a message and exit */ +/* -------------------------------------------------------------------------- */ + +static void error +( + char *message +) +{ + printf ("\n\n====== error: %s =====\n\n", message) ; + exit (1) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the residual, r = Ax-b or r = A'x=b and return maxnorm (r) */ +/* A' is the complex conjugate transpose, not the array transpose */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + Int transpose, + Int Ap [ ], + Int Ai [ ], + double Ax [ ] + , double Az [ ] +) +{ + Int i, j, p ; + double norm ; + + for (i = 0 ; i < n ; i++) + { + r [i] = -b [i] ; + rz[i] = -bz[i] ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + /* complex: r(j) += conj (Aij) * x (i) */ + r [j] += Ax [p] * x [i] ; + r [j] += Az [p] * xz[i] ; + rz[j] -= Az [p] * x [i] ; + rz[j] += Ax [p] * xz[i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + r [i] -= Az [p] * xz[j] ; + rz[i] += Az [p] * x [j] ; + rz[i] += Ax [p] * xz[j] ; + } + } + } + norm = 0. ; + for (i = 0 ; i < n ; i++) + { + norm = MAX (ABS (r [i], rz [i]), norm) ; + } + return (norm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], *Ax, *Cx, *Lx, *Ux, + *W, t [2], *Dx, rnorm, *Rb, *y, *Rs ; + double *Az, *Lz, *Uz, *Dz, *Cz, *Rbz, *yz ; + Int *Ap, *Ai, *Cp, *Ci, row, col, p, lnz, unz, nr, nc, *Lp, *Li, *Ui, *Up, + *P, *Q, *Lj, i, j, k, anz, nfr, nchains, *Qinit, fnpiv, lnz1, unz1, nz1, + status, *Front_npivcol, *Front_parent, *Chain_start, *Wi, *Pinit, n1, + *Chain_maxrows, *Chain_maxcols, *Front_1strow, *Front_leftmostdesc, + nzud, do_recip ; + void *Symbolic, *Numeric ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (t) ; + + printf ("\n%s demo: _xx_ version\n", UMFPACK_VERSION) ; + + /* get the default control parameters */ + umfpack_xx_defaults (Control) ; + + /* change the default print level for this demo */ + /* (otherwise, nothing will print) */ + Control [UMFPACK_PRL] = 6 ; + + /* print the license agreement */ + umfpack_xx_report_status (Control, UMFPACK_OK) ; + Control [UMFPACK_PRL] = 5 ; + + /* print the control parameters */ + umfpack_xx_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* print A and b, and convert A to column-form */ + /* ---------------------------------------------------------------------- */ + + /* print the right-hand-side */ + printf ("\nb: ") ; + (void) umfpack_xx_report_vector (n, b, bz, Control) ; + + /* print the triplet form of the matrix */ + printf ("\nA: ") ; + (void) umfpack_xx_report_triplet (n, n, nz, Arow, Acol, Aval, Avalz, + Control) ; + + /* convert to column form */ + nz1 = MAX (nz,1) ; /* ensure arrays are not of size zero. */ + Ap = (Int *) malloc ((n+1) * sizeof (Int)) ; + Ai = (Int *) malloc (nz1 * sizeof (Int)) ; + Ax = (double *) malloc (nz1 * sizeof (double)) ; + Az = (double *) malloc (nz1 * sizeof (double)) ; + if (!Ap || !Ai || !Ax || !Az) + { + error ("out of memory") ; + } + + status = umfpack_xx_triplet_to_col (n, n, nz, Arow, Acol, Aval, Avalz, + Ap, Ai, Ax, Az, (Int *) NULL) ; + + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_triplet_to_col failed") ; + } + + /* print the column-form of A */ + printf ("\nA: ") ; + (void) umfpack_xx_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_symbolic (n, n, Ap, Ai, Ax, Az, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_symbolic failed") ; + } + + /* print the symbolic factorization */ + + printf ("\nSymbolic factorization of A: ") ; + (void) umfpack_xx_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_numeric failed") ; + } + + /* print the numeric factorization */ + printf ("\nNumeric factorization of A: ") ; + (void) umfpack_xx_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_xx_solve failed") ; + } + printf ("\nx (solution of Ax=b): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_get_determinant (x, xz, r, Numeric, Info) ; + umfpack_xx_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_xx_get_determinant failed") ; + } + printf ("determinant: (%g", x [0]) ; + printf ("+ (%g)i", xz [0]) ; /* complex */ + printf (") * 10^(%g)\n", r [0]) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, broken down into steps */ + /* ---------------------------------------------------------------------- */ + + /* Rb = R*b */ + Rb = (double *) malloc (n * sizeof (double)) ; + Rbz = (double *) malloc (n * sizeof (double)) ; + y = (double *) malloc (n * sizeof (double)) ; + yz = (double *) malloc (n * sizeof (double)) ; + if (!Rb || !y) error ("out of memory") ; + if (!Rbz || !yz) error ("out of memory") ; + + status = umfpack_xx_scale (Rb, Rbz, b, bz, Numeric) ; + if (status < 0) error ("umfpack_xx_scale failed") ; + /* solve Ly = P*(Rb) */ + status = umfpack_xx_solve (UMFPACK_Pt_L, Ap, Ai, Ax, Az, y, yz, Rb, Rbz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_xx_solve failed") ; + /* solve UQ'x=y */ + status = umfpack_xx_solve (UMFPACK_U_Qt, Ap, Ai, Ax, Az, x, xz, y, yz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_xx_solve failed") ; + printf ("\nx (solution of Ax=b, solve is split into 3 steps): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + free (Rb) ; + free (Rbz) ; + free (y) ; + free (yz) ; + + /* ---------------------------------------------------------------------- */ + /* solve A'x=b */ + /* ---------------------------------------------------------------------- */ + + /* note that this is the complex conjugate transpose, A' */ + status = umfpack_xx_solve (UMFPACK_At, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_xx_report_info (Control, Info) ; + if (status < 0) + { + error ("umfpack_xx_solve failed") ; + } + printf ("\nx (solution of A'x=b): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify one numerical value in the column-form of A */ + /* ---------------------------------------------------------------------- */ + + /* change A (1,4), look for row index 1 in column 4. */ + row = 1 ; + col = 4 ; + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + if (row == Ai [p]) + { + printf ("\nchanging A (%ld,%ld) to zero\n", row, col) ; + Ax [p] = 0.0 ; + Az [p] = 0.0 ; + break ; + } + } + printf ("\nmodified A: ") ; + (void) umfpack_xx_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* The pattern (Ap and Ai) hasn't changed, so the symbolic factorization */ + /* doesn't have to be redone, no matter how much we change Ax. */ + + /* We don't need the Numeric object any more, so free it. */ + umfpack_xx_free_numeric (&Numeric) ; + + /* Note that a memory leak would have occurred if the old Numeric */ + /* had not been free'd with umfpack_xx_free_numeric above. */ + status = umfpack_xx_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_numeric failed") ; + } + printf ("\nNumeric factorization of modified A: ") ; + (void) umfpack_xx_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_xx_report_info (Control, Info) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_solve failed") ; + } + printf ("\nx (with modified A): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify all of the numerical values of A, but not the pattern */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < n ; col++) + { + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + row = Ai [p] ; + printf ("changing ") ; + /* complex: */ printf ("real part of ") ; + printf ("A (%ld,%ld) from %g", row, col, Ax [p]) ; + Ax [p] = Ax [p] + col*10 - row ; + printf (" to %g\n", Ax [p]) ; + } + } + printf ("\ncompletely modified A (same pattern): ") ; + (void) umfpack_xx_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Symbolic object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "symbolic.umf" */ + printf ("\nSaving symbolic object:\n") ; + status = umfpack_xx_save_symbolic (Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_save_symbolic failed") ; + } + printf ("\nFreeing symbolic object:\n") ; + umfpack_xx_free_symbolic (&Symbolic) ; + printf ("\nLoading symbolic object:\n") ; + status = umfpack_xx_load_symbolic (&Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_load_symbolic failed") ; + } + printf ("\nDone loading symbolic object\n") ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_xx_free_numeric (&Numeric) ; + status = umfpack_xx_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_numeric failed") ; + } + printf ("\nNumeric factorization of completely modified A: ") ; + (void) umfpack_xx_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_xx_report_info (Control, Info) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_solve failed") ; + } + printf ("\nx (with completely modified A): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free the symbolic and numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_xx_free_symbolic (&Symbolic) ; + umfpack_xx_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* C = transpose of A */ + /* ---------------------------------------------------------------------- */ + + Cp = (Int *) malloc ((n+1) * sizeof (Int)) ; + Ci = (Int *) malloc (nz1 * sizeof (Int)) ; + Cx = (double *) malloc (nz1 * sizeof (double)) ; + Cz = (double *) malloc (nz1 * sizeof (double)) ; + if (!Cp || !Ci || !Cx || !Cz) + { + error ("out of memory") ; + } + status = umfpack_xx_transpose (n, n, Ap, Ai, Ax, Az, + (Int *) NULL, (Int *) NULL, Cp, Ci, Cx, Cz, TRUE) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_transpose failed: ") ; + } + printf ("\nC (transpose of A): ") ; + (void) umfpack_xx_report_matrix (n, n, Cp, Ci, Cx, Cz, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_symbolic (n, n, Cp, Ci, Cx, Cz, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_xx_report_info (Control, Info) ; + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_symbolic failed") ; + } + printf ("\nSymbolic factorization of C: ") ; + (void) umfpack_xx_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* copy the contents of Symbolic into user arrays print them */ + /* ---------------------------------------------------------------------- */ + + printf ("\nGet the contents of the Symbolic object for C:\n") ; + printf ("(compare with umfpack_xx_report_symbolic output, above)\n") ; + Pinit = (Int *) malloc ((n+1) * sizeof (Int)) ; + Qinit = (Int *) malloc ((n+1) * sizeof (Int)) ; + Front_npivcol = (Int *) malloc ((n+1) * sizeof (Int)) ; + Front_1strow = (Int *) malloc ((n+1) * sizeof (Int)) ; + Front_leftmostdesc = (Int *) malloc ((n+1) * sizeof (Int)) ; + Front_parent = (Int *) malloc ((n+1) * sizeof (Int)) ; + Chain_start = (Int *) malloc ((n+1) * sizeof (Int)) ; + Chain_maxrows = (Int *) malloc ((n+1) * sizeof (Int)) ; + Chain_maxcols = (Int *) malloc ((n+1) * sizeof (Int)) ; + if (!Pinit || !Qinit || !Front_npivcol || !Front_parent || !Chain_start || + !Chain_maxrows || !Chain_maxcols || !Front_1strow || + !Front_leftmostdesc) + { + error ("out of memory") ; + } + + status = umfpack_xx_get_symbolic (&nr, &nc, &n1, &anz, &nfr, &nchains, + Pinit, Qinit, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + + if (status < 0) + { + error ("symbolic factorization invalid") ; + } + + printf ("From the Symbolic object, C is of dimension %ld-by-%ld\n", nr, nc); + printf (" with nz = %ld, number of fronts = %ld,\n", nz, nfr) ; + printf (" number of frontal matrix chains = %ld\n", nchains) ; + + printf ("\nPivot columns in each front, and parent of each front:\n") ; + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fnpiv = Front_npivcol [i] ; + printf (" Front %ld: parent front: %ld number of pivot cols: %ld\n", + i, Front_parent [i], fnpiv) ; + for (j = 0 ; j < fnpiv ; j++) + { + col = Qinit [k] ; + printf ( + " %ld-th pivot column is column %ld in original matrix\n", + k, col) ; + k++ ; + } + } + + printf ("\nNote that the column ordering, above, will be refined\n") ; + printf ("in the numeric factorization below. The assignment of pivot\n") ; + printf ("columns to frontal matrices will always remain unchanged.\n") ; + + printf ("\nTotal number of pivot columns in frontal matrices: %ld\n", k) ; + + printf ("\nFrontal matrix chains:\n") ; + for (j = 0 ; j < nchains ; j++) + { + printf (" Frontal matrices %ld to %ld are factorized in a single\n", + Chain_start [j], Chain_start [j+1] - 1) ; + printf (" working array of size %ld-by-%ld\n", + Chain_maxrows [j], Chain_maxcols [j]) ; + } + + /* ---------------------------------------------------------------------- */ + /* numeric factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_numeric (Cp, Ci, Cx, Cz, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + error ("umfpack_xx_numeric failed") ; + } + printf ("\nNumeric factorization of C: ") ; + (void) umfpack_xx_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* extract the LU factors of C and print them */ + /* ---------------------------------------------------------------------- */ + + if (umfpack_xx_get_lunz (&lnz, &unz, &nr, &nc, &nzud, Numeric) < 0) + { + error ("umfpack_xx_get_lunz failed") ; + } + /* ensure arrays are not of zero size */ + lnz1 = MAX (lnz,1) ; + unz1 = MAX (unz,1) ; + Lp = (Int *) malloc ((n+1) * sizeof (Int)) ; + Lj = (Int *) malloc (lnz1 * sizeof (Int)) ; + Lx = (double *) malloc (lnz1 * sizeof (double)) ; + Lz = (double *) malloc (lnz1 * sizeof (double)) ; + Up = (Int *) malloc ((n+1) * sizeof (Int)) ; + Ui = (Int *) malloc (unz1 * sizeof (Int)) ; + Ux = (double *) malloc (unz1 * sizeof (double)) ; + Uz = (double *) malloc (unz1 * sizeof (double)) ; + P = (Int *) malloc (n * sizeof (Int)) ; + Q = (Int *) malloc (n * sizeof (Int)) ; + Dx = (double *) NULL ; /* D vector not requested */ + Dz = (double *) NULL ; + Rs = (double *) malloc (n * sizeof (double)) ; + if (!Lp || !Lj || !Lx || !Lz || !Up || !Ui || !Ux || !Uz || !P || !Q || !Rs) + { + error ("out of memory") ; + } + status = umfpack_xx_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, + P, Q, Dx, Dz, &do_recip, Rs, Numeric) ; + if (status < 0) + { + error ("umfpack_xx_get_numeric failed") ; + } + + printf ("\nL (lower triangular factor of C): ") ; + (void) umfpack_xx_report_matrix (n, n, Lp, Lj, Lx, Lz, 0, Control) ; + printf ("\nU (upper triangular factor of C): ") ; + (void) umfpack_xx_report_matrix (n, n, Up, Ui, Ux, Uz, 1, Control) ; + printf ("\nP: ") ; + (void) umfpack_xx_report_perm (n, P, Control) ; + printf ("\nQ: ") ; + (void) umfpack_xx_report_perm (n, Q, Control) ; + printf ("\nScale factors: row i of A is to be ") ; + if (do_recip) + { + printf ("multiplied by the ith scale factor\n") ; + } + else + { + printf ("divided by the ith scale factor\n") ; + } + for (i = 0 ; i < n ; i++) printf ("%ld: %g\n", i, Rs [i]) ; + + /* ---------------------------------------------------------------------- */ + /* convert L to triplet form and print it */ + /* ---------------------------------------------------------------------- */ + + /* Note that L is in row-form, so it is the row indices that are created */ + /* by umfpack_xx_col_to_triplet. */ + + printf ("\nConverting L to triplet form, and printing it:\n") ; + Li = (Int *) malloc (lnz1 * sizeof (Int)) ; + if (!Li) + { + error ("out of memory") ; + } + if (umfpack_xx_col_to_triplet (n, Lp, Li) < 0) + { + error ("umfpack_xx_col_to_triplet failed") ; + } + printf ("\nL, in triplet form: ") ; + (void) umfpack_xx_report_triplet (n, n, lnz, Li, Lj, Lx, Lz, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Numeric object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "numeric.umf" */ + printf ("\nSaving numeric object:\n") ; + status = umfpack_xx_save_numeric (Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_save_numeric failed") ; + } + printf ("\nFreeing numeric object:\n") ; + umfpack_xx_free_numeric (&Numeric) ; + printf ("\nLoading numeric object:\n") ; + status = umfpack_xx_load_numeric (&Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_load_numeric failed") ; + } + printf ("\nDone loading numeric object\n") ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_xx_solve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_xx_report_info (Control, Info) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_solve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b again, using umfpack_xx_wsolve instead */ + /* ---------------------------------------------------------------------- */ + + printf ("\nSolving C'x=b again, using umfpack_xx_wsolve instead:\n") ; + Wi = (Int *) malloc (n * sizeof (Int)) ; + :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + :: WSIZE is 5 for the real case, 10 for complex. + :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + W = (double *) malloc (WSIZE*n * sizeof (double)) ; + if (!Wi || !W) + { + error ("out of memory") ; + } + + status = umfpack_xx_wsolve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info, Wi, W) ; + umfpack_xx_report_info (Control, Info) ; + if (status < 0) + { + umfpack_xx_report_status (Control, status) ; + error ("umfpack_xx_wsolve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_xx_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free everything */ + /* ---------------------------------------------------------------------- */ + + /* This is not strictly required since the process is exiting and the */ + /* system will reclaim the memory anyway. It's useful, though, just as */ + /* a list of what is currently malloc'ed by this program. Plus, it's */ + /* always a good habit to explicitly free whatever you malloc. */ + + free (Ap) ; + free (Ai) ; + free (Ax) ; + free (Az) ; + + free (Cp) ; + free (Ci) ; + free (Cx) ; + free (Cz) ; + + free (Pinit) ; + free (Qinit) ; + free (Front_npivcol) ; + free (Front_1strow) ; + free (Front_leftmostdesc) ; + free (Front_parent) ; + free (Chain_start) ; + free (Chain_maxrows) ; + free (Chain_maxcols) ; + + free (Lp) ; + free (Lj) ; + free (Lx) ; + free (Lz) ; + + free (Up) ; + free (Ui) ; + free (Ux) ; + free (Uz) ; + + free (P) ; + free (Q) ; + + free (Li) ; + + free (Wi) ; + free (W) ; + + umfpack_xx_free_symbolic (&Symbolic) ; + umfpack_xx_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* print the total time spent in this demo */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (t) ; + printf ("\numfpack_xx_demo complete.\nTotal time: %5.2f seconds" + " (CPU time), %5.2f seconds (wallclock time)\n", t [1], t [0]) ; + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.c @@ -0,0 +1,791 @@ +/* ========================================================================== */ +/* === umfpack_zi_demo ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + A demo of UMFPACK: umfpack_zi_* version. + + First, factor and solve a 5-by-5 system, Ax=b, using default parameters. + Then solve A'x=b using the factors of A. Modify one entry (A (1,4) = 0, + where the row and column indices range from 0 to 4. The pattern of A + has not changed (it has explicitly zero entry), so a reanalysis with + umfpack_zi_symbolic does not need to be done. Refactorize (with + umfpack_zi_numeric), and solve Ax=b. Note that the pivot ordering has + changed. Next, change all of the entries in A, but not the pattern. + + Finally, compute C = A', and do the symbolic and numeric factorization of C. + Factorizing A' can sometimes be better than factorizing A itself (less work + and memory usage). Solve C'x=b twice; the solution is the same as the + solution to Ax=b. + + A note about zero-sized arrays: UMFPACK uses many user-provided arrays of + size n (order of the matrix), and of size nz (the number of nonzeros in a + matrix). n cannot be zero; UMFPACK does not handle zero-dimensioned arrays. + However, nz can be zero. If you attempt to malloc an array of size nz = 0, + however, malloc will return a null pointer which UMFPACK will report as a + "missing argument." Thus, nz1 in this code is set to MAX (nz,1), and + similarly for lnz and unz. Lnz can never be zero, however, since L is always + unit diagonal. +*/ + +/* -------------------------------------------------------------------------- */ +/* definitions */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "umfpack.h" + +/* use a cheap approximate absolute value for complex numbers: */ +#define ABS(x,z) ((x) >= 0 ? (x) : -(x)) + ((z) >= 0 ? (z) : -(z)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ +/* triplet form of the matrix. The triplets can be in any order. */ +/* -------------------------------------------------------------------------- */ + +static int n = 5, nz = 12 ; +static int Arow [ ] = { 0, 4, 1, 1, 2, 2, 0, 1, 2, 3, 4, 4} ; +static int Acol [ ] = { 0, 4, 0, 2, 1, 2, 1, 4, 3, 2, 1, 2} ; +static double Aval [ ] = {2., 1., 3., 4., -1., -3., 3., 6., 2., 1., 4., 2.} ; +static double Avalz[ ] = {1., .4, .1, .2, -1., -.2, 0., 6., 3., 0., .3, .3} ; +static double b [ ] = {8., 45., -3., 3., 19.}, x [5], r [5] ; +static double bz[ ] = {1., -5., -2., 0., 2.2}, xz[5], rz[5] ; + +/* Avalz, bz: imaginary part of A and b */ + +/* -------------------------------------------------------------------------- */ +/* error: print a message and exit */ +/* -------------------------------------------------------------------------- */ + +static void error +( + char *message +) +{ + printf ("\n\n====== error: %s =====\n\n", message) ; + exit (1) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the residual, r = Ax-b or r = A'x=b and return maxnorm (r) */ +/* A' is the complex conjugate transpose, not the array transpose */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + int transpose, + int Ap [ ], + int Ai [ ], + double Ax [ ] + , double Az [ ] +) +{ + int i, j, p ; + double norm ; + + for (i = 0 ; i < n ; i++) + { + r [i] = -b [i] ; + rz[i] = -bz[i] ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + /* complex: r(j) += conj (Aij) * x (i) */ + r [j] += Ax [p] * x [i] ; + r [j] += Az [p] * xz[i] ; + rz[j] -= Az [p] * x [i] ; + rz[j] += Ax [p] * xz[i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + r [i] -= Az [p] * xz[j] ; + rz[i] += Az [p] * x [j] ; + rz[i] += Ax [p] * xz[j] ; + } + } + } + norm = 0. ; + for (i = 0 ; i < n ; i++) + { + norm = MAX (ABS (r [i], rz [i]), norm) ; + } + return (norm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], *Ax, *Cx, *Lx, *Ux, + *W, t [2], *Dx, rnorm, *Rb, *y, *Rs ; + double *Az, *Lz, *Uz, *Dz, *Cz, *Rbz, *yz ; + int *Ap, *Ai, *Cp, *Ci, row, col, p, lnz, unz, nr, nc, *Lp, *Li, *Ui, *Up, + *P, *Q, *Lj, i, j, k, anz, nfr, nchains, *Qinit, fnpiv, lnz1, unz1, nz1, + status, *Front_npivcol, *Front_parent, *Chain_start, *Wi, *Pinit, n1, + *Chain_maxrows, *Chain_maxcols, *Front_1strow, *Front_leftmostdesc, + nzud, do_recip ; + void *Symbolic, *Numeric ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (t) ; + + printf ("\n%s demo: _zi_ version\n", UMFPACK_VERSION) ; + + /* get the default control parameters */ + umfpack_zi_defaults (Control) ; + + /* change the default print level for this demo */ + /* (otherwise, nothing will print) */ + Control [UMFPACK_PRL] = 6 ; + + /* print the license agreement */ + umfpack_zi_report_status (Control, UMFPACK_OK) ; + Control [UMFPACK_PRL] = 5 ; + + /* print the control parameters */ + umfpack_zi_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* print A and b, and convert A to column-form */ + /* ---------------------------------------------------------------------- */ + + /* print the right-hand-side */ + printf ("\nb: ") ; + (void) umfpack_zi_report_vector (n, b, bz, Control) ; + + /* print the triplet form of the matrix */ + printf ("\nA: ") ; + (void) umfpack_zi_report_triplet (n, n, nz, Arow, Acol, Aval, Avalz, + Control) ; + + /* convert to column form */ + nz1 = MAX (nz,1) ; /* ensure arrays are not of size zero. */ + Ap = (int *) malloc ((n+1) * sizeof (int)) ; + Ai = (int *) malloc (nz1 * sizeof (int)) ; + Ax = (double *) malloc (nz1 * sizeof (double)) ; + Az = (double *) malloc (nz1 * sizeof (double)) ; + if (!Ap || !Ai || !Ax || !Az) + { + error ("out of memory") ; + } + + status = umfpack_zi_triplet_to_col (n, n, nz, Arow, Acol, Aval, Avalz, + Ap, Ai, Ax, Az, (int *) NULL) ; + + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_triplet_to_col failed") ; + } + + /* print the column-form of A */ + printf ("\nA: ") ; + (void) umfpack_zi_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_symbolic (n, n, Ap, Ai, Ax, Az, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_symbolic failed") ; + } + + /* print the symbolic factorization */ + + printf ("\nSymbolic factorization of A: ") ; + (void) umfpack_zi_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_numeric failed") ; + } + + /* print the numeric factorization */ + printf ("\nNumeric factorization of A: ") ; + (void) umfpack_zi_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_zi_solve failed") ; + } + printf ("\nx (solution of Ax=b): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_get_determinant (x, xz, r, Numeric, Info) ; + umfpack_zi_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_zi_get_determinant failed") ; + } + printf ("determinant: (%g", x [0]) ; + printf ("+ (%g)i", xz [0]) ; /* complex */ + printf (") * 10^(%g)\n", r [0]) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, broken down into steps */ + /* ---------------------------------------------------------------------- */ + + /* Rb = R*b */ + Rb = (double *) malloc (n * sizeof (double)) ; + Rbz = (double *) malloc (n * sizeof (double)) ; + y = (double *) malloc (n * sizeof (double)) ; + yz = (double *) malloc (n * sizeof (double)) ; + if (!Rb || !y) error ("out of memory") ; + if (!Rbz || !yz) error ("out of memory") ; + + status = umfpack_zi_scale (Rb, Rbz, b, bz, Numeric) ; + if (status < 0) error ("umfpack_zi_scale failed") ; + /* solve Ly = P*(Rb) */ + status = umfpack_zi_solve (UMFPACK_Pt_L, Ap, Ai, Ax, Az, y, yz, Rb, Rbz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_zi_solve failed") ; + /* solve UQ'x=y */ + status = umfpack_zi_solve (UMFPACK_U_Qt, Ap, Ai, Ax, Az, x, xz, y, yz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_zi_solve failed") ; + printf ("\nx (solution of Ax=b, solve is split into 3 steps): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + free (Rb) ; + free (Rbz) ; + free (y) ; + free (yz) ; + + /* ---------------------------------------------------------------------- */ + /* solve A'x=b */ + /* ---------------------------------------------------------------------- */ + + /* note that this is the complex conjugate transpose, A' */ + status = umfpack_zi_solve (UMFPACK_At, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zi_report_info (Control, Info) ; + if (status < 0) + { + error ("umfpack_zi_solve failed") ; + } + printf ("\nx (solution of A'x=b): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify one numerical value in the column-form of A */ + /* ---------------------------------------------------------------------- */ + + /* change A (1,4), look for row index 1 in column 4. */ + row = 1 ; + col = 4 ; + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + if (row == Ai [p]) + { + printf ("\nchanging A (%d,%d) to zero\n", row, col) ; + Ax [p] = 0.0 ; + Az [p] = 0.0 ; + break ; + } + } + printf ("\nmodified A: ") ; + (void) umfpack_zi_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* The pattern (Ap and Ai) hasn't changed, so the symbolic factorization */ + /* doesn't have to be redone, no matter how much we change Ax. */ + + /* We don't need the Numeric object any more, so free it. */ + umfpack_zi_free_numeric (&Numeric) ; + + /* Note that a memory leak would have occurred if the old Numeric */ + /* had not been free'd with umfpack_zi_free_numeric above. */ + status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_numeric failed") ; + } + printf ("\nNumeric factorization of modified A: ") ; + (void) umfpack_zi_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zi_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_solve failed") ; + } + printf ("\nx (with modified A): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify all of the numerical values of A, but not the pattern */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < n ; col++) + { + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + row = Ai [p] ; + printf ("changing ") ; + /* complex: */ printf ("real part of ") ; + printf ("A (%d,%d) from %g", row, col, Ax [p]) ; + Ax [p] = Ax [p] + col*10 - row ; + printf (" to %g\n", Ax [p]) ; + } + } + printf ("\ncompletely modified A (same pattern): ") ; + (void) umfpack_zi_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Symbolic object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "symbolic.umf" */ + printf ("\nSaving symbolic object:\n") ; + status = umfpack_zi_save_symbolic (Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_save_symbolic failed") ; + } + printf ("\nFreeing symbolic object:\n") ; + umfpack_zi_free_symbolic (&Symbolic) ; + printf ("\nLoading symbolic object:\n") ; + status = umfpack_zi_load_symbolic (&Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_load_symbolic failed") ; + } + printf ("\nDone loading symbolic object\n") ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_zi_free_numeric (&Numeric) ; + status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_numeric failed") ; + } + printf ("\nNumeric factorization of completely modified A: ") ; + (void) umfpack_zi_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zi_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_solve failed") ; + } + printf ("\nx (with completely modified A): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free the symbolic and numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_zi_free_symbolic (&Symbolic) ; + umfpack_zi_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* C = transpose of A */ + /* ---------------------------------------------------------------------- */ + + Cp = (int *) malloc ((n+1) * sizeof (int)) ; + Ci = (int *) malloc (nz1 * sizeof (int)) ; + Cx = (double *) malloc (nz1 * sizeof (double)) ; + Cz = (double *) malloc (nz1 * sizeof (double)) ; + if (!Cp || !Ci || !Cx || !Cz) + { + error ("out of memory") ; + } + status = umfpack_zi_transpose (n, n, Ap, Ai, Ax, Az, + (int *) NULL, (int *) NULL, Cp, Ci, Cx, Cz, TRUE) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_transpose failed: ") ; + } + printf ("\nC (transpose of A): ") ; + (void) umfpack_zi_report_matrix (n, n, Cp, Ci, Cx, Cz, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_symbolic (n, n, Cp, Ci, Cx, Cz, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_zi_report_info (Control, Info) ; + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_symbolic failed") ; + } + printf ("\nSymbolic factorization of C: ") ; + (void) umfpack_zi_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* copy the contents of Symbolic into user arrays print them */ + /* ---------------------------------------------------------------------- */ + + printf ("\nGet the contents of the Symbolic object for C:\n") ; + printf ("(compare with umfpack_zi_report_symbolic output, above)\n") ; + Pinit = (int *) malloc ((n+1) * sizeof (int)) ; + Qinit = (int *) malloc ((n+1) * sizeof (int)) ; + Front_npivcol = (int *) malloc ((n+1) * sizeof (int)) ; + Front_1strow = (int *) malloc ((n+1) * sizeof (int)) ; + Front_leftmostdesc = (int *) malloc ((n+1) * sizeof (int)) ; + Front_parent = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_start = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_maxrows = (int *) malloc ((n+1) * sizeof (int)) ; + Chain_maxcols = (int *) malloc ((n+1) * sizeof (int)) ; + if (!Pinit || !Qinit || !Front_npivcol || !Front_parent || !Chain_start || + !Chain_maxrows || !Chain_maxcols || !Front_1strow || + !Front_leftmostdesc) + { + error ("out of memory") ; + } + + status = umfpack_zi_get_symbolic (&nr, &nc, &n1, &anz, &nfr, &nchains, + Pinit, Qinit, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + + if (status < 0) + { + error ("symbolic factorization invalid") ; + } + + printf ("From the Symbolic object, C is of dimension %d-by-%d\n", nr, nc); + printf (" with nz = %d, number of fronts = %d,\n", nz, nfr) ; + printf (" number of frontal matrix chains = %d\n", nchains) ; + + printf ("\nPivot columns in each front, and parent of each front:\n") ; + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fnpiv = Front_npivcol [i] ; + printf (" Front %d: parent front: %d number of pivot cols: %d\n", + i, Front_parent [i], fnpiv) ; + for (j = 0 ; j < fnpiv ; j++) + { + col = Qinit [k] ; + printf ( + " %d-th pivot column is column %d in original matrix\n", + k, col) ; + k++ ; + } + } + + printf ("\nNote that the column ordering, above, will be refined\n") ; + printf ("in the numeric factorization below. The assignment of pivot\n") ; + printf ("columns to frontal matrices will always remain unchanged.\n") ; + + printf ("\nTotal number of pivot columns in frontal matrices: %d\n", k) ; + + printf ("\nFrontal matrix chains:\n") ; + for (j = 0 ; j < nchains ; j++) + { + printf (" Frontal matrices %d to %d are factorized in a single\n", + Chain_start [j], Chain_start [j+1] - 1) ; + printf (" working array of size %d-by-%d\n", + Chain_maxrows [j], Chain_maxcols [j]) ; + } + + /* ---------------------------------------------------------------------- */ + /* numeric factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_numeric (Cp, Ci, Cx, Cz, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + error ("umfpack_zi_numeric failed") ; + } + printf ("\nNumeric factorization of C: ") ; + (void) umfpack_zi_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* extract the LU factors of C and print them */ + /* ---------------------------------------------------------------------- */ + + if (umfpack_zi_get_lunz (&lnz, &unz, &nr, &nc, &nzud, Numeric) < 0) + { + error ("umfpack_zi_get_lunz failed") ; + } + /* ensure arrays are not of zero size */ + lnz1 = MAX (lnz,1) ; + unz1 = MAX (unz,1) ; + Lp = (int *) malloc ((n+1) * sizeof (int)) ; + Lj = (int *) malloc (lnz1 * sizeof (int)) ; + Lx = (double *) malloc (lnz1 * sizeof (double)) ; + Lz = (double *) malloc (lnz1 * sizeof (double)) ; + Up = (int *) malloc ((n+1) * sizeof (int)) ; + Ui = (int *) malloc (unz1 * sizeof (int)) ; + Ux = (double *) malloc (unz1 * sizeof (double)) ; + Uz = (double *) malloc (unz1 * sizeof (double)) ; + P = (int *) malloc (n * sizeof (int)) ; + Q = (int *) malloc (n * sizeof (int)) ; + Dx = (double *) NULL ; /* D vector not requested */ + Dz = (double *) NULL ; + Rs = (double *) malloc (n * sizeof (double)) ; + if (!Lp || !Lj || !Lx || !Lz || !Up || !Ui || !Ux || !Uz || !P || !Q || !Rs) + { + error ("out of memory") ; + } + status = umfpack_zi_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, + P, Q, Dx, Dz, &do_recip, Rs, Numeric) ; + if (status < 0) + { + error ("umfpack_zi_get_numeric failed") ; + } + + printf ("\nL (lower triangular factor of C): ") ; + (void) umfpack_zi_report_matrix (n, n, Lp, Lj, Lx, Lz, 0, Control) ; + printf ("\nU (upper triangular factor of C): ") ; + (void) umfpack_zi_report_matrix (n, n, Up, Ui, Ux, Uz, 1, Control) ; + printf ("\nP: ") ; + (void) umfpack_zi_report_perm (n, P, Control) ; + printf ("\nQ: ") ; + (void) umfpack_zi_report_perm (n, Q, Control) ; + printf ("\nScale factors: row i of A is to be ") ; + if (do_recip) + { + printf ("multiplied by the ith scale factor\n") ; + } + else + { + printf ("divided by the ith scale factor\n") ; + } + for (i = 0 ; i < n ; i++) printf ("%d: %g\n", i, Rs [i]) ; + + /* ---------------------------------------------------------------------- */ + /* convert L to triplet form and print it */ + /* ---------------------------------------------------------------------- */ + + /* Note that L is in row-form, so it is the row indices that are created */ + /* by umfpack_zi_col_to_triplet. */ + + printf ("\nConverting L to triplet form, and printing it:\n") ; + Li = (int *) malloc (lnz1 * sizeof (int)) ; + if (!Li) + { + error ("out of memory") ; + } + if (umfpack_zi_col_to_triplet (n, Lp, Li) < 0) + { + error ("umfpack_zi_col_to_triplet failed") ; + } + printf ("\nL, in triplet form: ") ; + (void) umfpack_zi_report_triplet (n, n, lnz, Li, Lj, Lx, Lz, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Numeric object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "numeric.umf" */ + printf ("\nSaving numeric object:\n") ; + status = umfpack_zi_save_numeric (Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_save_numeric failed") ; + } + printf ("\nFreeing numeric object:\n") ; + umfpack_zi_free_numeric (&Numeric) ; + printf ("\nLoading numeric object:\n") ; + status = umfpack_zi_load_numeric (&Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_load_numeric failed") ; + } + printf ("\nDone loading numeric object\n") ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zi_solve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zi_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_solve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b again, using umfpack_zi_wsolve instead */ + /* ---------------------------------------------------------------------- */ + + printf ("\nSolving C'x=b again, using umfpack_zi_wsolve instead:\n") ; + Wi = (int *) malloc (n * sizeof (int)) ; + W = (double *) malloc (10*n * sizeof (double)) ; + if (!Wi || !W) + { + error ("out of memory") ; + } + + status = umfpack_zi_wsolve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info, Wi, W) ; + umfpack_zi_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zi_report_status (Control, status) ; + error ("umfpack_zi_wsolve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_zi_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free everything */ + /* ---------------------------------------------------------------------- */ + + /* This is not strictly required since the process is exiting and the */ + /* system will reclaim the memory anyway. It's useful, though, just as */ + /* a list of what is currently malloc'ed by this program. Plus, it's */ + /* always a good habit to explicitly free whatever you malloc. */ + + free (Ap) ; + free (Ai) ; + free (Ax) ; + free (Az) ; + + free (Cp) ; + free (Ci) ; + free (Cx) ; + free (Cz) ; + + free (Pinit) ; + free (Qinit) ; + free (Front_npivcol) ; + free (Front_1strow) ; + free (Front_leftmostdesc) ; + free (Front_parent) ; + free (Chain_start) ; + free (Chain_maxrows) ; + free (Chain_maxcols) ; + + free (Lp) ; + free (Lj) ; + free (Lx) ; + free (Lz) ; + + free (Up) ; + free (Ui) ; + free (Ux) ; + free (Uz) ; + + free (P) ; + free (Q) ; + + free (Li) ; + + free (Wi) ; + free (W) ; + + umfpack_zi_free_symbolic (&Symbolic) ; + umfpack_zi_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* print the total time spent in this demo */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (t) ; + printf ("\numfpack_zi_demo complete.\nTotal time: %5.2f seconds" + " (CPU time), %5.2f seconds (wallclock time)\n", t [1], t [0]) ; + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.out b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.out @@ -0,0 +1,1542 @@ + +UMFPACK V4.4 (Jan. 28, 2005) demo: _zi_ version + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: http://www.cise.ufl.edu/research/sparse/umfpack + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double complex + Int (generic integer) defined as: int + + 0: print level: 5 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 16 (in bytes) + + +b: dense vector, n = 5. + 0 : (8 + 1i) + 1 : (45 - 5i) + 2 : (-3 - 2i) + 3 : (3 + 0i) + 4 : (19 + 2.2i) + dense vector OK + + +A: triplet-form matrix, n_row = 5, n_col = 5 nz = 12. + 0 : 0 0 (2 + 1i) + 1 : 4 4 (1 + 0.4i) + 2 : 1 0 (3 + 0.1i) + 3 : 1 2 (4 + 0.2i) + 4 : 2 1 (-1 - 1i) + 5 : 2 2 (-3 - 0.2i) + 6 : 0 1 (3 + 0i) + 7 : 1 4 (6 + 6i) + 8 : 2 3 (2 + 3i) + 9 : 3 2 (1 + 0i) + 10 : 4 1 (4 + 0.3i) + 11 : 4 2 (2 + 0.3i) + triplet-form matrix OK + + +A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (3 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3 + 0i) + row 2 : (-1 - 1i) + row 4 : (4 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4 + 0.2i) + row 2 : (-3 - 0.2i) + row 3 : (1 + 0i) + row 4 : (2 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (6 + 6i) + row 4 : (1 + 0.4i) + column-form matrix OK + + +Symbolic factorization of A: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 84 (MBytes): 0.0 + estimated peak size (Units): 2542 (MBytes): 0.0 + estimated final size (Units): 25 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Numeric factorization of A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 99 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.34629e-01 + max abs. value on diagonal of U: 1.77313e+00 + reciprocal condition number estimate: 7.59e-02 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.166667) + 1 : (0.0518135) + 2 : (0.0980392) + 3 : (1) + 4 : (0.125) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.207254 + 0.0103627i) + row 3 : (0.25 + 0.0375i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.379275 - 0.174093i) + + column 3: length 1. + row 4 : (3.00161 + 1.2864i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.5 + 0.0375i) + + row 2: length 1. + col 4 : (0.5 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.294118 - 0.0196078i) + col 4 : (-0.0980392 - 0.0980392i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.196078 + 0.294118i) + 1 : (1 + 0i) + 2 : (0.333333 + 0.166667i) + 3 : (0.125 + 0.05i) + 4 : (-1.6422 - 0.668715i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.77e+00 + estimate of reciprocal of condition number: 7.59e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.23000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.87e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.57000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +x (solution of Ax=b): dense vector, n = 5. + 0 : (0.121188 - 0.561001i) + 1 : (2.39887 + 0.666938i) + 2 : (3 + 0i) + 3 : (1.57395 - 1.52801i) + 4 : (2.3876 - 3.04245i) + dense vector OK + +maxnorm of residual: 6.21725e-15 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + +determinant: (-1.7814+ (2.3784)i) * 10^(2) + +x (solution of Ax=b, solve is split into 3 steps): dense vector, n = 5. + 0 : (0.121188 - 0.561001i) + 1 : (2.39887 + 0.666938i) + 2 : (3 + 0i) + 3 : (1.57395 - 1.52801i) + 4 : (2.3876 - 3.04245i) + dense vector OK + +maxnorm of residual: 6.21725e-15 + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.77e+00 + estimate of reciprocal of condition number: 7.59e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 6.06e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of A'x=b): dense vector, n = 5. + 0 : (3.39246 + 0.13257i) + 1 : (0.31463 + 1.38626i) + 2 : (0.461538 + 0.692308i) + 3 : (-20.9089 - 1.55801i) + 4 : (9.04015 - 0.613724i) + dense vector OK + +maxnorm of residual: 7.68703e-15 + + +changing A (1,4) to zero + +modified A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (3 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3 + 0i) + row 2 : (-1 - 1i) + row 4 : (4 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4 + 0.2i) + row 2 : (-3 - 0.2i) + row 3 : (1 + 0i) + row 4 : (2 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (0 + 0i) + row 4 : (1 + 0.4i) + column-form matrix OK + + +Numeric factorization of modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.02000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 97 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 1 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 17 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.34629e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.35e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.166667) + 1 : (0.136986) + 2 : (0.0980392) + 3 : (1) + 4 : (0.125) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.547945 + 0.0273973i) + row 3 : (0.25 + 0.0375i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (1.00274 - 0.460274i) + + column 3: length 0. Start of Lchain. + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.5 + 0.0375i) + + row 2: length 1. + col 4 : (0.5 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.294118 - 0.0196078i) + col 4 : (-0.0980392 - 0.0980392i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.196078 + 0.294118i) + 1 : (1 + 0i) + 2 : (0.333333 + 0.166667i) + 3 : (0.125 + 0.05i) + 4 : (-0.50137 + 0.230137i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.02000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 19 76% + Numeric final size (Units) 106 98 92% + Numeric final size (MBytes) 0.0 0.0 92% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 1.70000e+01 25% + nz in L (incl diagonal) 10 8 80% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 12 80% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.35e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 8 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.15000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.33e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.01 + solve mflops (wall clock time): 0.05 + + total symbolic + numeric + solve flops: 5.32000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with modified A): dense vector, n = 5. + 0 : (10.9256 - 2.23085i) + 1 : (-5.36071 - 1.82131i) + 2 : (3 + 0i) + 3 : (-1.60191 - 1.88814i) + 4 : (32.7361 - 2.90097i) + dense vector OK + +maxnorm of residual: 3.9968e-15 + +changing real part of A (0,0) from 2 to 2 +changing real part of A (1,0) from 3 to 2 +changing real part of A (0,1) from 3 to 13 +changing real part of A (2,1) from -1 to 7 +changing real part of A (4,1) from 4 to 10 +changing real part of A (1,2) from 4 to 23 +changing real part of A (2,2) from -3 to 15 +changing real part of A (3,2) from 1 to 18 +changing real part of A (4,2) from 2 to 18 +changing real part of A (2,3) from 2 to 30 +changing real part of A (1,4) from 0 to 39 +changing real part of A (4,4) from 1 to 37 + +completely modified A (same pattern): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (2 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (13 + 0i) + row 2 : (7 - 1i) + row 4 : (10 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (23 + 0.2i) + row 2 : (15 - 0.2i) + row 3 : (18 + 0i) + row 4 : (18 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (30 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (39 + 0i) + row 4 : (37 + 0.4i) + column-form matrix OK + + +Saving symbolic object: + +Freeing symbolic object: + +Loading symbolic object: + +Done loading symbolic object + +Numeric factorization of completely modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.60000e+01 + maximum sum (abs (rows of A)): 6.60000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 99 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.39754e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.40e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.0625) + 1 : (0.0155521) + 2 : (0.0177936) + 3 : (0.0555556) + 4 : (0.0151515) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.357698 + 0.00311042i) + row 3 : (0.272727 + 0.00454545i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.204044 - 0.0895801i) + + column 3: length 1. + row 4 : (1.0818 - 0.0116951i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.151515 + 0.00454545i) + + row 2: length 1. + col 4 : (0.8125 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (0.266904 - 0.00355872i) + col 4 : (0.124555 - 0.0177936i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.533808 + 0.0533808i) + 1 : (1 + 0i) + 2 : (0.125 + 0.0625i) + 3 : (0.560606 + 0.00606061i) + 4 : (-0.329747 + 0.0696386i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.60000e+01 + maximum sum (abs (rows of A)): 6.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.40e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.40e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.23000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 4.75e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.57000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with completely modified A): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.92582e-15 + + +C (transpose of A): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 - 1i) + row 1 : (13 + 0i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (2 - 0.1i) + row 2 : (23 - 0.2i) + row 4 : (39 + 0i) + + column 2: start: 5 end: 7 entries: 3 + row 1 : (7 + 1i) + row 2 : (15 + 0.2i) + row 3 : (30 - 3i) + + column 3: start: 8 end: 8 entries: 1 + row 2 : (18 + 0i) + + column 4: start: 9 end: 11 entries: 3 + row 1 : (10 - 0.3i) + row 2 : (18 - 0.3i) + row 4 : (37 - 0.4i) + column-form matrix OK + + +Symbolic factorization of C: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 85 (MBytes): 0.0 + estimated peak size (Units): 2543 (MBytes): 0.0 + estimated final size (Units): 26 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Get the contents of the Symbolic object for C: +(compare with umfpack_zi_report_symbolic output, above) +From the Symbolic object, C is of dimension 5-by-5 + with nz = 12, number of fronts = 1, + number of frontal matrix chains = 1 + +Pivot columns in each front, and parent of each front: + Front 0: parent front: -1 number of pivot cols: 3 + 0-th pivot column is column 3 in original matrix + 1-th pivot column is column 2 in original matrix + 2-th pivot column is column 0 in original matrix + +Note that the column ordering, above, will be refined +in the numeric factorization below. The assignment of pivot +columns to frontal matrices will always remain unchanged. + +Total number of pivot columns in frontal matrices: 3 + +Frontal matrix chains: + Frontal matrices 0 to 0 are factorized in a single + working array of size 3-by-3 + +Numeric factorization of C: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 100 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2528 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 5 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.40964e-01 + max abs. value on diagonal of U: 9.13625e-01 + reciprocal condition number estimate: 2.64e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.196078) + 1 : (0.0319489) + 2 : (0.0133869) + 3 : (0.030303) + 4 : (0.013089) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 1. + row 4 : (0.240091 + 0.0591529i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.847284 + 0.423642i) + + column 3: length 1. + row 4 : (0.659838 - 0.0126577i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.510471 + 0i) + + row 2: length 1. + col 4 : (0.392157 - 0.0196078i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 3. + col 1 : (0.200803 + 0.00267738i) + col 3 : (0.240964 - 0.00401606i) + col 4 : (0.307898 - 0.00267738i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.240964 + 0i) + 1 : (0.909091 - 0.0909091i) + 2 : (0.392157 - 0.196078i) + 3 : (0.484293 - 0.0052356i) + 4 : (-0.677403 - 0.143059i) + dense vector OK + + Numeric object: OK + + +L (lower triangular factor of C): row-form matrix, n_row 5 n_col 5, nz = 8. + + row 0: start: 0 end: 0 entries: 1 + column 0 : (1 + 0i) + + row 1: start: 1 end: 1 entries: 1 + column 1 : (1 + 0i) + + row 2: start: 2 end: 2 entries: 1 + column 2 : (1 + 0i) + + row 3: start: 3 end: 3 entries: 1 + column 3 : (1 + 0i) + + row 4: start: 4 end: 7 entries: 4 + column 1 : (0.240091 + 0.0591529i) + column 2 : (0.847284 + 0.423642i) + column 3 : (0.659838 - 0.0126577i) + column 4 : (1 + 0i) + row-form matrix OK + + +U (upper triangular factor of C): column-form matrix, n_row 5 n_col 5, nz = 10. + + column 0: start: 0 end: 0 entries: 1 + row 0 : (0.240964 + 0i) + + column 1: start: 1 end: 2 entries: 2 + row 0 : (0.200803 + 0.00267738i) + row 1 : (0.909091 - 0.0909091i) + + column 2: start: 3 end: 3 entries: 1 + row 2 : (0.392157 - 0.196078i) + + column 3: start: 4 end: 5 entries: 2 + row 0 : (0.240964 - 0.00401606i) + row 3 : (0.484293 - 0.0052356i) + + column 4: start: 6 end: 9 entries: 4 + row 0 : (0.307898 - 0.00267738i) + row 2 : (0.392157 - 0.0196078i) + row 3 : (0.510471 + 0i) + row 4 : (-0.677403 - 0.143059i) + column-form matrix OK + + +P: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Scale factors: row i of A is to be multiplied by the ith scale factor +0: 0.196078 +1: 0.0319489 +2: 0.0133869 +3: 0.030303 +4: 0.013089 + +Converting L to triplet form, and printing it: + +L, in triplet form: triplet-form matrix, n_row = 5, n_col = 5 nz = 8. + 0 : 0 0 (1 + 0i) + 1 : 1 1 (1 + 0i) + 2 : 2 2 (1 + 0i) + 3 : 3 3 (1 + 0i) + 4 : 4 1 (0.240091 + 0.0591529i) + 5 : 4 2 (0.847284 + 0.423642i) + 6 : 4 3 (0.659838 - 0.0126577i) + 7 : 4 4 (1 + 0i) + triplet-form matrix OK + + +Saving numeric object: + +Freeing numeric object: + +Loading numeric object: + +Done loading numeric object + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 85 80 94% + peak size (Units) 2543 2528 99% + final size (Units) 26 22 85% + Numeric final size (Units) 107 101 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2738 2723 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.41e-01 + max abs. value on diagonal of U: 9.14e-01 + estimate of reciprocal of condition number: 2.64e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 8.89e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.6552e-15 + + +Solving C'x=b again, using umfpack_zi_wsolve instead: + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: int + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 85 80 94% + peak size (Units) 2543 2528 99% + final size (Units) 26 22 85% + Numeric final size (Units) 107 101 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2738 2723 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.41e-01 + max abs. value on diagonal of U: 9.14e-01 + estimate of reciprocal of condition number: 2.64e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 8.89e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.6552e-15 + + +umfpack_zi_demo complete. +Total time: 0.00 seconds (CPU time), 0.01 seconds (wallclock time) diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.sed b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.sed new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zi_demo.sed @@ -0,0 +1,8 @@ +/::/d +1,$s/_xx_/_zi_/g +1,$s/Int/int/g +1,$s/WSIZE/10/ +1,$s/%ld/%d/g +/define ABS/ { + s/ABS/ABS(x,z) ((x) >= 0 ? (x) : -(x)) + ((z) >= 0 ? (z) : -(z))/ + } diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.c b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.c @@ -0,0 +1,791 @@ +/* ========================================================================== */ +/* === umfpack_zl_demo ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + A demo of UMFPACK: umfpack_zl_* version. + + First, factor and solve a 5-by-5 system, Ax=b, using default parameters. + Then solve A'x=b using the factors of A. Modify one entry (A (1,4) = 0, + where the row and column indices range from 0 to 4. The pattern of A + has not changed (it has explicitly zero entry), so a reanalysis with + umfpack_zl_symbolic does not need to be done. Refactorize (with + umfpack_zl_numeric), and solve Ax=b. Note that the pivot ordering has + changed. Next, change all of the entries in A, but not the pattern. + + Finally, compute C = A', and do the symbolic and numeric factorization of C. + Factorizing A' can sometimes be better than factorizing A itself (less work + and memory usage). Solve C'x=b twice; the solution is the same as the + solution to Ax=b. + + A note about zero-sized arrays: UMFPACK uses many user-provided arrays of + size n (order of the matrix), and of size nz (the number of nonzeros in a + matrix). n cannot be zero; UMFPACK does not handle zero-dimensioned arrays. + However, nz can be zero. If you attempt to malloc an array of size nz = 0, + however, malloc will return a null pointer which UMFPACK will report as a + "missing argument." Thus, nz1 in this code is set to MAX (nz,1), and + similarly for lnz and unz. Lnz can never be zero, however, since L is always + unit diagonal. +*/ + +/* -------------------------------------------------------------------------- */ +/* definitions */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "umfpack.h" + +/* use a cheap approximate absolute value for complex numbers: */ +#define ABS(x,z) ((x) >= 0 ? (x) : -(x)) + ((z) >= 0 ? (z) : -(z)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ +/* triplet form of the matrix. The triplets can be in any order. */ +/* -------------------------------------------------------------------------- */ + +static long n = 5, nz = 12 ; +static long Arow [ ] = { 0, 4, 1, 1, 2, 2, 0, 1, 2, 3, 4, 4} ; +static long Acol [ ] = { 0, 4, 0, 2, 1, 2, 1, 4, 3, 2, 1, 2} ; +static double Aval [ ] = {2., 1., 3., 4., -1., -3., 3., 6., 2., 1., 4., 2.} ; +static double Avalz[ ] = {1., .4, .1, .2, -1., -.2, 0., 6., 3., 0., .3, .3} ; +static double b [ ] = {8., 45., -3., 3., 19.}, x [5], r [5] ; +static double bz[ ] = {1., -5., -2., 0., 2.2}, xz[5], rz[5] ; + +/* Avalz, bz: imaginary part of A and b */ + +/* -------------------------------------------------------------------------- */ +/* error: print a message and exit */ +/* -------------------------------------------------------------------------- */ + +static void error +( + char *message +) +{ + printf ("\n\n====== error: %s =====\n\n", message) ; + exit (1) ; +} + + +/* -------------------------------------------------------------------------- */ +/* resid: compute the residual, r = Ax-b or r = A'x=b and return maxnorm (r) */ +/* A' is the complex conjugate transpose, not the array transpose */ +/* -------------------------------------------------------------------------- */ + +static double resid +( + long transpose, + long Ap [ ], + long Ai [ ], + double Ax [ ] + , double Az [ ] +) +{ + long i, j, p ; + double norm ; + + for (i = 0 ; i < n ; i++) + { + r [i] = -b [i] ; + rz[i] = -bz[i] ; + } + if (transpose) + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + /* complex: r(j) += conj (Aij) * x (i) */ + r [j] += Ax [p] * x [i] ; + r [j] += Az [p] * xz[i] ; + rz[j] -= Az [p] * x [i] ; + rz[j] += Ax [p] * xz[i] ; + } + } + } + else + { + for (j = 0 ; j < n ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + r [i] += Ax [p] * x [j] ; + r [i] -= Az [p] * xz[j] ; + rz[i] += Az [p] * x [j] ; + rz[i] += Ax [p] * xz[j] ; + } + } + } + norm = 0. ; + for (i = 0 ; i < n ; i++) + { + norm = MAX (ABS (r [i], rz [i]), norm) ; + } + return (norm) ; +} + + +/* -------------------------------------------------------------------------- */ +/* main program */ +/* -------------------------------------------------------------------------- */ + +int main (int argc, char **argv) +{ + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], *Ax, *Cx, *Lx, *Ux, + *W, t [2], *Dx, rnorm, *Rb, *y, *Rs ; + double *Az, *Lz, *Uz, *Dz, *Cz, *Rbz, *yz ; + long *Ap, *Ai, *Cp, *Ci, row, col, p, lnz, unz, nr, nc, *Lp, *Li, *Ui, *Up, + *P, *Q, *Lj, i, j, k, anz, nfr, nchains, *Qinit, fnpiv, lnz1, unz1, nz1, + status, *Front_npivcol, *Front_parent, *Chain_start, *Wi, *Pinit, n1, + *Chain_maxrows, *Chain_maxcols, *Front_1strow, *Front_leftmostdesc, + nzud, do_recip ; + void *Symbolic, *Numeric ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (t) ; + + printf ("\n%s demo: _zl_ version\n", UMFPACK_VERSION) ; + + /* get the default control parameters */ + umfpack_zl_defaults (Control) ; + + /* change the default print level for this demo */ + /* (otherwise, nothing will print) */ + Control [UMFPACK_PRL] = 6 ; + + /* print the license agreement */ + umfpack_zl_report_status (Control, UMFPACK_OK) ; + Control [UMFPACK_PRL] = 5 ; + + /* print the control parameters */ + umfpack_zl_report_control (Control) ; + + /* ---------------------------------------------------------------------- */ + /* print A and b, and convert A to column-form */ + /* ---------------------------------------------------------------------- */ + + /* print the right-hand-side */ + printf ("\nb: ") ; + (void) umfpack_zl_report_vector (n, b, bz, Control) ; + + /* print the triplet form of the matrix */ + printf ("\nA: ") ; + (void) umfpack_zl_report_triplet (n, n, nz, Arow, Acol, Aval, Avalz, + Control) ; + + /* convert to column form */ + nz1 = MAX (nz,1) ; /* ensure arrays are not of size zero. */ + Ap = (long *) malloc ((n+1) * sizeof (long)) ; + Ai = (long *) malloc (nz1 * sizeof (long)) ; + Ax = (double *) malloc (nz1 * sizeof (double)) ; + Az = (double *) malloc (nz1 * sizeof (double)) ; + if (!Ap || !Ai || !Ax || !Az) + { + error ("out of memory") ; + } + + status = umfpack_zl_triplet_to_col (n, n, nz, Arow, Acol, Aval, Avalz, + Ap, Ai, Ax, Az, (long *) NULL) ; + + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_triplet_to_col failed") ; + } + + /* print the column-form of A */ + printf ("\nA: ") ; + (void) umfpack_zl_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_symbolic (n, n, Ap, Ai, Ax, Az, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_symbolic failed") ; + } + + /* print the symbolic factorization */ + + printf ("\nSymbolic factorization of A: ") ; + (void) umfpack_zl_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_numeric failed") ; + } + + /* print the numeric factorization */ + printf ("\nNumeric factorization of A: ") ; + (void) umfpack_zl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_zl_solve failed") ; + } + printf ("\nx (solution of Ax=b): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_get_determinant (x, xz, r, Numeric, Info) ; + umfpack_zl_report_status (Control, status) ; + if (status < 0) + { + error ("umfpack_zl_get_determinant failed") ; + } + printf ("determinant: (%g", x [0]) ; + printf ("+ (%g)i", xz [0]) ; /* complex */ + printf (") * 10^(%g)\n", r [0]) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, broken down into steps */ + /* ---------------------------------------------------------------------- */ + + /* Rb = R*b */ + Rb = (double *) malloc (n * sizeof (double)) ; + Rbz = (double *) malloc (n * sizeof (double)) ; + y = (double *) malloc (n * sizeof (double)) ; + yz = (double *) malloc (n * sizeof (double)) ; + if (!Rb || !y) error ("out of memory") ; + if (!Rbz || !yz) error ("out of memory") ; + + status = umfpack_zl_scale (Rb, Rbz, b, bz, Numeric) ; + if (status < 0) error ("umfpack_zl_scale failed") ; + /* solve Ly = P*(Rb) */ + status = umfpack_zl_solve (UMFPACK_Pt_L, Ap, Ai, Ax, Az, y, yz, Rb, Rbz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_zl_solve failed") ; + /* solve UQ'x=y */ + status = umfpack_zl_solve (UMFPACK_U_Qt, Ap, Ai, Ax, Az, x, xz, y, yz, + Numeric, Control, Info) ; + if (status < 0) error ("umfpack_zl_solve failed") ; + printf ("\nx (solution of Ax=b, solve is split into 3 steps): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + free (Rb) ; + free (Rbz) ; + free (y) ; + free (yz) ; + + /* ---------------------------------------------------------------------- */ + /* solve A'x=b */ + /* ---------------------------------------------------------------------- */ + + /* note that this is the complex conjugate transpose, A' */ + status = umfpack_zl_solve (UMFPACK_At, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zl_report_info (Control, Info) ; + if (status < 0) + { + error ("umfpack_zl_solve failed") ; + } + printf ("\nx (solution of A'x=b): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify one numerical value in the column-form of A */ + /* ---------------------------------------------------------------------- */ + + /* change A (1,4), look for row index 1 in column 4. */ + row = 1 ; + col = 4 ; + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + if (row == Ai [p]) + { + printf ("\nchanging A (%ld,%ld) to zero\n", row, col) ; + Ax [p] = 0.0 ; + Az [p] = 0.0 ; + break ; + } + } + printf ("\nmodified A: ") ; + (void) umfpack_zl_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* The pattern (Ap and Ai) hasn't changed, so the symbolic factorization */ + /* doesn't have to be redone, no matter how much we change Ax. */ + + /* We don't need the Numeric object any more, so free it. */ + umfpack_zl_free_numeric (&Numeric) ; + + /* Note that a memory leak would have occurred if the old Numeric */ + /* had not been free'd with umfpack_zl_free_numeric above. */ + status = umfpack_zl_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_numeric failed") ; + } + printf ("\nNumeric factorization of modified A: ") ; + (void) umfpack_zl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_solve failed") ; + } + printf ("\nx (with modified A): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* modify all of the numerical values of A, but not the pattern */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < n ; col++) + { + for (p = Ap [col] ; p < Ap [col+1] ; p++) + { + row = Ai [p] ; + printf ("changing ") ; + /* complex: */ printf ("real part of ") ; + printf ("A (%ld,%ld) from %g", row, col, Ax [p]) ; + Ax [p] = Ax [p] + col*10 - row ; + printf (" to %g\n", Ax [p]) ; + } + } + printf ("\ncompletely modified A (same pattern): ") ; + (void) umfpack_zl_report_matrix (n, n, Ap, Ai, Ax, Az, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Symbolic object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "symbolic.umf" */ + printf ("\nSaving symbolic object:\n") ; + status = umfpack_zl_save_symbolic (Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_save_symbolic failed") ; + } + printf ("\nFreeing symbolic object:\n") ; + umfpack_zl_free_symbolic (&Symbolic) ; + printf ("\nLoading symbolic object:\n") ; + status = umfpack_zl_load_symbolic (&Symbolic, (char *) NULL) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_load_symbolic failed") ; + } + printf ("\nDone loading symbolic object\n") ; + + /* ---------------------------------------------------------------------- */ + /* redo the numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_zl_free_numeric (&Numeric) ; + status = umfpack_zl_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_numeric failed") ; + } + printf ("\nNumeric factorization of completely modified A: ") ; + (void) umfpack_zl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* solve Ax=b, with the modified A */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_solve (UMFPACK_A, Ap, Ai, Ax, Az, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_solve failed") ; + } + printf ("\nx (with completely modified A): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (FALSE, Ap, Ai, Ax, Az) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free the symbolic and numeric factorization */ + /* ---------------------------------------------------------------------- */ + + umfpack_zl_free_symbolic (&Symbolic) ; + umfpack_zl_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* C = transpose of A */ + /* ---------------------------------------------------------------------- */ + + Cp = (long *) malloc ((n+1) * sizeof (long)) ; + Ci = (long *) malloc (nz1 * sizeof (long)) ; + Cx = (double *) malloc (nz1 * sizeof (double)) ; + Cz = (double *) malloc (nz1 * sizeof (double)) ; + if (!Cp || !Ci || !Cx || !Cz) + { + error ("out of memory") ; + } + status = umfpack_zl_transpose (n, n, Ap, Ai, Ax, Az, + (long *) NULL, (long *) NULL, Cp, Ci, Cx, Cz, TRUE) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_transpose failed: ") ; + } + printf ("\nC (transpose of A): ") ; + (void) umfpack_zl_report_matrix (n, n, Cp, Ci, Cx, Cz, 1, Control) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_symbolic (n, n, Cp, Ci, Cx, Cz, &Symbolic, + Control, Info) ; + if (status < 0) + { + umfpack_zl_report_info (Control, Info) ; + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_symbolic failed") ; + } + printf ("\nSymbolic factorization of C: ") ; + (void) umfpack_zl_report_symbolic (Symbolic, Control) ; + + /* ---------------------------------------------------------------------- */ + /* copy the contents of Symbolic into user arrays print them */ + /* ---------------------------------------------------------------------- */ + + printf ("\nGet the contents of the Symbolic object for C:\n") ; + printf ("(compare with umfpack_zl_report_symbolic output, above)\n") ; + Pinit = (long *) malloc ((n+1) * sizeof (long)) ; + Qinit = (long *) malloc ((n+1) * sizeof (long)) ; + Front_npivcol = (long *) malloc ((n+1) * sizeof (long)) ; + Front_1strow = (long *) malloc ((n+1) * sizeof (long)) ; + Front_leftmostdesc = (long *) malloc ((n+1) * sizeof (long)) ; + Front_parent = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_start = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_maxrows = (long *) malloc ((n+1) * sizeof (long)) ; + Chain_maxcols = (long *) malloc ((n+1) * sizeof (long)) ; + if (!Pinit || !Qinit || !Front_npivcol || !Front_parent || !Chain_start || + !Chain_maxrows || !Chain_maxcols || !Front_1strow || + !Front_leftmostdesc) + { + error ("out of memory") ; + } + + status = umfpack_zl_get_symbolic (&nr, &nc, &n1, &anz, &nfr, &nchains, + Pinit, Qinit, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + + if (status < 0) + { + error ("symbolic factorization invalid") ; + } + + printf ("From the Symbolic object, C is of dimension %ld-by-%ld\n", nr, nc); + printf (" with nz = %ld, number of fronts = %ld,\n", nz, nfr) ; + printf (" number of frontal matrix chains = %ld\n", nchains) ; + + printf ("\nPivot columns in each front, and parent of each front:\n") ; + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fnpiv = Front_npivcol [i] ; + printf (" Front %ld: parent front: %ld number of pivot cols: %ld\n", + i, Front_parent [i], fnpiv) ; + for (j = 0 ; j < fnpiv ; j++) + { + col = Qinit [k] ; + printf ( + " %ld-th pivot column is column %ld in original matrix\n", + k, col) ; + k++ ; + } + } + + printf ("\nNote that the column ordering, above, will be refined\n") ; + printf ("in the numeric factorization below. The assignment of pivot\n") ; + printf ("columns to frontal matrices will always remain unchanged.\n") ; + + printf ("\nTotal number of pivot columns in frontal matrices: %ld\n", k) ; + + printf ("\nFrontal matrix chains:\n") ; + for (j = 0 ; j < nchains ; j++) + { + printf (" Frontal matrices %ld to %ld are factorized in a single\n", + Chain_start [j], Chain_start [j+1] - 1) ; + printf (" working array of size %ld-by-%ld\n", + Chain_maxrows [j], Chain_maxcols [j]) ; + } + + /* ---------------------------------------------------------------------- */ + /* numeric factorization of C */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_numeric (Cp, Ci, Cx, Cz, Symbolic, &Numeric, + Control, Info) ; + if (status < 0) + { + error ("umfpack_zl_numeric failed") ; + } + printf ("\nNumeric factorization of C: ") ; + (void) umfpack_zl_report_numeric (Numeric, Control) ; + + /* ---------------------------------------------------------------------- */ + /* extract the LU factors of C and print them */ + /* ---------------------------------------------------------------------- */ + + if (umfpack_zl_get_lunz (&lnz, &unz, &nr, &nc, &nzud, Numeric) < 0) + { + error ("umfpack_zl_get_lunz failed") ; + } + /* ensure arrays are not of zero size */ + lnz1 = MAX (lnz,1) ; + unz1 = MAX (unz,1) ; + Lp = (long *) malloc ((n+1) * sizeof (long)) ; + Lj = (long *) malloc (lnz1 * sizeof (long)) ; + Lx = (double *) malloc (lnz1 * sizeof (double)) ; + Lz = (double *) malloc (lnz1 * sizeof (double)) ; + Up = (long *) malloc ((n+1) * sizeof (long)) ; + Ui = (long *) malloc (unz1 * sizeof (long)) ; + Ux = (double *) malloc (unz1 * sizeof (double)) ; + Uz = (double *) malloc (unz1 * sizeof (double)) ; + P = (long *) malloc (n * sizeof (long)) ; + Q = (long *) malloc (n * sizeof (long)) ; + Dx = (double *) NULL ; /* D vector not requested */ + Dz = (double *) NULL ; + Rs = (double *) malloc (n * sizeof (double)) ; + if (!Lp || !Lj || !Lx || !Lz || !Up || !Ui || !Ux || !Uz || !P || !Q || !Rs) + { + error ("out of memory") ; + } + status = umfpack_zl_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, + P, Q, Dx, Dz, &do_recip, Rs, Numeric) ; + if (status < 0) + { + error ("umfpack_zl_get_numeric failed") ; + } + + printf ("\nL (lower triangular factor of C): ") ; + (void) umfpack_zl_report_matrix (n, n, Lp, Lj, Lx, Lz, 0, Control) ; + printf ("\nU (upper triangular factor of C): ") ; + (void) umfpack_zl_report_matrix (n, n, Up, Ui, Ux, Uz, 1, Control) ; + printf ("\nP: ") ; + (void) umfpack_zl_report_perm (n, P, Control) ; + printf ("\nQ: ") ; + (void) umfpack_zl_report_perm (n, Q, Control) ; + printf ("\nScale factors: row i of A is to be ") ; + if (do_recip) + { + printf ("multiplied by the ith scale factor\n") ; + } + else + { + printf ("divided by the ith scale factor\n") ; + } + for (i = 0 ; i < n ; i++) printf ("%ld: %g\n", i, Rs [i]) ; + + /* ---------------------------------------------------------------------- */ + /* convert L to triplet form and print it */ + /* ---------------------------------------------------------------------- */ + + /* Note that L is in row-form, so it is the row indices that are created */ + /* by umfpack_zl_col_to_triplet. */ + + printf ("\nConverting L to triplet form, and printing it:\n") ; + Li = (long *) malloc (lnz1 * sizeof (long)) ; + if (!Li) + { + error ("out of memory") ; + } + if (umfpack_zl_col_to_triplet (n, Lp, Li) < 0) + { + error ("umfpack_zl_col_to_triplet failed") ; + } + printf ("\nL, in triplet form: ") ; + (void) umfpack_zl_report_triplet (n, n, lnz, Li, Lj, Lx, Lz, Control) ; + + /* ---------------------------------------------------------------------- */ + /* save the Numeric object to file, free it, and load it back in */ + /* ---------------------------------------------------------------------- */ + + /* use the default filename, "numeric.umf" */ + printf ("\nSaving numeric object:\n") ; + status = umfpack_zl_save_numeric (Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_save_numeric failed") ; + } + printf ("\nFreeing numeric object:\n") ; + umfpack_zl_free_numeric (&Numeric) ; + printf ("\nLoading numeric object:\n") ; + status = umfpack_zl_load_numeric (&Numeric, (char *) NULL) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_load_numeric failed") ; + } + printf ("\nDone loading numeric object\n") ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b */ + /* ---------------------------------------------------------------------- */ + + status = umfpack_zl_solve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info) ; + umfpack_zl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_solve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* solve C'x=b again, using umfpack_zl_wsolve instead */ + /* ---------------------------------------------------------------------- */ + + printf ("\nSolving C'x=b again, using umfpack_zl_wsolve instead:\n") ; + Wi = (long *) malloc (n * sizeof (long)) ; + W = (double *) malloc (10*n * sizeof (double)) ; + if (!Wi || !W) + { + error ("out of memory") ; + } + + status = umfpack_zl_wsolve (UMFPACK_At, Cp, Ci, Cx, Cz, x, xz, b, bz, + Numeric, Control, Info, Wi, W) ; + umfpack_zl_report_info (Control, Info) ; + if (status < 0) + { + umfpack_zl_report_status (Control, status) ; + error ("umfpack_zl_wsolve failed") ; + } + printf ("\nx (solution of C'x=b): ") ; + (void) umfpack_zl_report_vector (n, x, xz, Control) ; + rnorm = resid (TRUE, Cp, Ci, Cx, Cz) ; + printf ("maxnorm of residual: %g\n\n", rnorm) ; + + /* ---------------------------------------------------------------------- */ + /* free everything */ + /* ---------------------------------------------------------------------- */ + + /* This is not strictly required since the process is exiting and the */ + /* system will reclaim the memory anyway. It's useful, though, just as */ + /* a list of what is currently malloc'ed by this program. Plus, it's */ + /* always a good habit to explicitly free whatever you malloc. */ + + free (Ap) ; + free (Ai) ; + free (Ax) ; + free (Az) ; + + free (Cp) ; + free (Ci) ; + free (Cx) ; + free (Cz) ; + + free (Pinit) ; + free (Qinit) ; + free (Front_npivcol) ; + free (Front_1strow) ; + free (Front_leftmostdesc) ; + free (Front_parent) ; + free (Chain_start) ; + free (Chain_maxrows) ; + free (Chain_maxcols) ; + + free (Lp) ; + free (Lj) ; + free (Lx) ; + free (Lz) ; + + free (Up) ; + free (Ui) ; + free (Ux) ; + free (Uz) ; + + free (P) ; + free (Q) ; + + free (Li) ; + + free (Wi) ; + free (W) ; + + umfpack_zl_free_symbolic (&Symbolic) ; + umfpack_zl_free_numeric (&Numeric) ; + + /* ---------------------------------------------------------------------- */ + /* print the total time spent in this demo */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (t) ; + printf ("\numfpack_zl_demo complete.\nTotal time: %5.2f seconds" + " (CPU time), %5.2f seconds (wallclock time)\n", t [1], t [0]) ; + return (0) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.out b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.out @@ -0,0 +1,1541 @@ + +UMFPACK V4.4 (Jan. 28, 2005) demo: _zl_ version + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: http://www.cise.ufl.edu/research/sparse/umfpack + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +UMFPACK V4.4 (Jan. 28, 2005), Control: + + Matrix entry defined as: double complex + Int (generic integer) defined as: long + + 0: print level: 5 + 1: dense row parameter: 0.2 + "dense" rows have > max (16, (0.2)*16*sqrt(n_col) entries) + 2: dense column parameter: 0.2 + "dense" columns have > max (16, (0.2)*16*sqrt(n_row) entries) + 3: pivot tolerance: 0.1 + 4: block size for dense matrix kernels: 32 + 5: strategy: 0 (auto) + 6: initial allocation ratio: 0.7 + 7: max iterative refinement steps: 2 + 12: 2-by-2 pivot tolerance: 0.01 + 13: Q fixed during numerical factorization: 0 (auto) + 14: AMD dense row/col parameter: 10 + "dense" rows/columns have > max (16, (10)*sqrt(n)) entries + Only used if the AMD ordering is used. + 15: diagonal pivot tolerance: 0.001 + Only used if diagonal pivoting is attempted. + 16: scaling: 1 (divide each row by sum of abs. values in each row) + 17: frontal matrix allocation ratio: 0.5 + 18: drop tolerance: 0 + 19: AMD and COLAMD aggressive absorption: 1 (yes) + + The following options can only be changed at compile-time: + 8: BLAS library used: none. UMFPACK will be slow. + 9: compiled for ANSI C (uses malloc, free, realloc, and printf) + 10: CPU timer is POSIX times ( ) routine. + 11: compiled for normal operation (debugging disabled) + computer/operating system: Linux + size of int: 4 long: 4 Int: 4 pointer: 4 double: 8 Entry: 16 (in bytes) + + +b: dense vector, n = 5. + 0 : (8 + 1i) + 1 : (45 - 5i) + 2 : (-3 - 2i) + 3 : (3 + 0i) + 4 : (19 + 2.2i) + dense vector OK + + +A: triplet-form matrix, n_row = 5, n_col = 5 nz = 12. + 0 : 0 0 (2 + 1i) + 1 : 4 4 (1 + 0.4i) + 2 : 1 0 (3 + 0.1i) + 3 : 1 2 (4 + 0.2i) + 4 : 2 1 (-1 - 1i) + 5 : 2 2 (-3 - 0.2i) + 6 : 0 1 (3 + 0i) + 7 : 1 4 (6 + 6i) + 8 : 2 3 (2 + 3i) + 9 : 3 2 (1 + 0i) + 10 : 4 1 (4 + 0.3i) + 11 : 4 2 (2 + 0.3i) + triplet-form matrix OK + + +A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (3 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3 + 0i) + row 2 : (-1 - 1i) + row 4 : (4 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4 + 0.2i) + row 2 : (-3 - 0.2i) + row 3 : (1 + 0i) + row 4 : (2 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (6 + 6i) + row 4 : (1 + 0.4i) + column-form matrix OK + + +Symbolic factorization of A: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 84 (MBytes): 0.0 + estimated peak size (Units): 2542 (MBytes): 0.0 + estimated final size (Units): 25 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Numeric factorization of A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 99 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.34629e-01 + max abs. value on diagonal of U: 1.77313e+00 + reciprocal condition number estimate: 7.59e-02 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.166667) + 1 : (0.0518135) + 2 : (0.0980392) + 3 : (1) + 4 : (0.125) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.207254 + 0.0103627i) + row 3 : (0.25 + 0.0375i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.379275 - 0.174093i) + + column 3: length 1. + row 4 : (3.00161 + 1.2864i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.5 + 0.0375i) + + row 2: length 1. + col 4 : (0.5 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.294118 - 0.0196078i) + col 4 : (-0.0980392 - 0.0980392i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.196078 + 0.294118i) + 1 : (1 + 0i) + 2 : (0.333333 + 0.166667i) + 3 : (0.125 + 0.05i) + 4 : (-1.6422 - 0.668715i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.77e+00 + estimate of reciprocal of condition number: 7.59e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.23000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.87e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.57000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + + +x (solution of Ax=b): dense vector, n = 5. + 0 : (0.121188 - 0.561001i) + 1 : (2.39887 + 0.666938i) + 2 : (3 + 0i) + 3 : (1.57395 - 1.52801i) + 4 : (2.3876 - 3.04245i) + dense vector OK + +maxnorm of residual: 6.21725e-15 + + +UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +UMFPACK V4.4 (Jan. 28, 2005): OK + +determinant: (-1.7814+ (2.3784)i) * 10^(2) + +x (solution of Ax=b, solve is split into 3 steps): dense vector, n = 5. + 0 : (0.121188 - 0.561001i) + 1 : (2.39887 + 0.666938i) + 2 : (3 + 0i) + 3 : (1.57395 - 1.52801i) + 4 : (2.3876 - 3.04245i) + dense vector OK + +maxnorm of residual: 6.21725e-15 + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.93000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.77e+00 + estimate of reciprocal of condition number: 7.59e-02 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 6.06e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of A'x=b): dense vector, n = 5. + 0 : (3.39246 + 0.13257i) + 1 : (0.31463 + 1.38626i) + 2 : (0.461538 + 0.692308i) + 3 : (-20.9089 - 1.55801i) + 4 : (9.04015 - 0.613724i) + dense vector OK + +maxnorm of residual: 7.68703e-15 + + +changing A (1,4) to zero + +modified A: column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (3 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (3 + 0i) + row 2 : (-1 - 1i) + row 4 : (4 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (4 + 0.2i) + row 2 : (-3 - 0.2i) + row 3 : (1 + 0i) + row 4 : (2 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (2 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (0 + 0i) + row 4 : (1 + 0.4i) + column-form matrix OK + + +Numeric factorization of modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.02000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 97 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 1 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 17 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.34629e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.35e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.166667) + 1 : (0.136986) + 2 : (0.0980392) + 3 : (1) + 4 : (0.125) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.547945 + 0.0273973i) + row 3 : (0.25 + 0.0375i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (1.00274 - 0.460274i) + + column 3: length 0. Start of Lchain. + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.5 + 0.0375i) + + row 2: length 1. + col 4 : (0.5 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (-0.294118 - 0.0196078i) + col 4 : (-0.0980392 - 0.0980392i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.196078 + 0.294118i) + 1 : (1 + 0i) + 2 : (0.333333 + 0.166667i) + 3 : (0.125 + 0.05i) + 4 : (-0.50137 + 0.230137i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.00000e+00 + maximum sum (abs (rows of A)): 1.02000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 19 76% + Numeric final size (Units) 106 98 92% + Numeric final size (MBytes) 0.0 0.0 92% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 1.70000e+01 25% + nz in L (incl diagonal) 10 8 80% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 12 80% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.35e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.35e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 8 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.15000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 7.33e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.32000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with modified A): dense vector, n = 5. + 0 : (10.9256 - 2.23085i) + 1 : (-5.36071 - 1.82131i) + 2 : (3 + 0i) + 3 : (-1.60191 - 1.88814i) + 4 : (32.7361 - 2.90097i) + dense vector OK + +maxnorm of residual: 3.9968e-15 + +changing real part of A (0,0) from 2 to 2 +changing real part of A (1,0) from 3 to 2 +changing real part of A (0,1) from 3 to 13 +changing real part of A (2,1) from -1 to 7 +changing real part of A (4,1) from 4 to 10 +changing real part of A (1,2) from 4 to 23 +changing real part of A (2,2) from -3 to 15 +changing real part of A (3,2) from 1 to 18 +changing real part of A (4,2) from 2 to 18 +changing real part of A (2,3) from 2 to 30 +changing real part of A (1,4) from 0 to 39 +changing real part of A (4,4) from 1 to 37 + +completely modified A (same pattern): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 + 1i) + row 1 : (2 + 0.1i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (13 + 0i) + row 2 : (7 - 1i) + row 4 : (10 + 0.3i) + + column 2: start: 5 end: 8 entries: 4 + row 1 : (23 + 0.2i) + row 2 : (15 - 0.2i) + row 3 : (18 + 0i) + row 4 : (18 + 0.3i) + + column 3: start: 9 end: 9 entries: 1 + row 2 : (30 + 3i) + + column 4: start: 10 end: 11 entries: 2 + row 1 : (39 + 0i) + row 4 : (37 + 0.4i) + column-form matrix OK + + +Saving symbolic object: + +Freeing symbolic object: + +Loading symbolic object: + +Done loading symbolic object + +Numeric factorization of completely modified A: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 1.60000e+01 + maximum sum (abs (rows of A)): 6.60000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 99 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2527 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 4 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 4 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.39754e-01 + max abs. value on diagonal of U: 1.00000e+00 + reciprocal condition number estimate: 1.40e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.0625) + 1 : (0.0155521) + 2 : (0.0177936) + 3 : (0.0555556) + 4 : (0.0151515) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 2. + row 4 : (0.357698 + 0.00311042i) + row 3 : (0.272727 + 0.00454545i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.204044 - 0.0895801i) + + column 3: length 1. + row 4 : (1.0818 - 0.0116951i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.151515 + 0.00454545i) + + row 2: length 1. + col 4 : (0.8125 + 0i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 2. + col 1 : (0.266904 - 0.00355872i) + col 4 : (0.124555 - 0.0177936i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.533808 + 0.0533808i) + 1 : (1 + 0i) + 2 : (0.125 + 0.0625i) + 3 : (0.560606 + 0.00606061i) + 4 : (-0.329747 + 0.0696386i) + dense vector OK + + Numeric object: OK + + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 1.60000e+01 + maximum sum (abs (rows of A)): 6.60000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 84 79 94% + peak size (Units) 2542 2527 99% + final size (Units) 25 21 84% + Numeric final size (Units) 106 100 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2737 2722 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 10 9 90% + nz in U (incl diagonal) 10 9 90% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 9 + nz in U (incl diagonal), if none dropped 9 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 1.40e-01 + max abs. value on diagonal of U: 1.00e+00 + estimate of reciprocal of condition number: 1.40e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 5.23000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 4.75e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.57000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (with completely modified A): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.92582e-15 + + +C (transpose of A): column-form matrix, n_row 5 n_col 5, nz = 12. + + column 0: start: 0 end: 1 entries: 2 + row 0 : (2 - 1i) + row 1 : (13 + 0i) + + column 1: start: 2 end: 4 entries: 3 + row 0 : (2 - 0.1i) + row 2 : (23 - 0.2i) + row 4 : (39 + 0i) + + column 2: start: 5 end: 7 entries: 3 + row 1 : (7 + 1i) + row 2 : (15 + 0.2i) + row 3 : (30 - 3i) + + column 3: start: 8 end: 8 entries: 1 + row 2 : (18 + 0i) + + column 4: start: 9 end: 11 entries: 3 + row 1 : (10 - 0.3i) + row 2 : (18 - 0.3i) + row 4 : (37 - 0.4i) + column-form matrix OK + + +Symbolic factorization of C: Symbolic object: + matrix to be factorized: + n_row: 5 n_col: 5 + number of entries: 12 + block size used for dense matrix kernels: 32 + strategy used: unsymmetric + ordering used: colamd on A + + performn column etree postorder: yes + prefer diagonal pivoting (attempt P=Q): no + variable-size part of Numeric object: + minimum initial size (Units): 85 (MBytes): 0.0 + estimated peak size (Units): 2543 (MBytes): 0.0 + estimated final size (Units): 26 (MBytes): 0.0 + symbolic factorization memory usage (Units): 144 (MBytes): 0.0 + frontal matrices / supercolumns: + number of frontal chains: 1 + number of frontal matrices: 1 + largest frontal matrix row dimension: 3 + largest frontal matrix column dimension: 3 + + Frontal chain: 0. Frontal matrices 0 to 0 + Largest frontal matrix in Frontal chain: 3-by-3 + Front: 0 pivot cols: 3 (pivot columns 0 to 2) + pivot row candidates: 2 to 4 + leftmost descendant: 0 + 1st new candidate row : 2 + parent: (none) + +Initial column permutation, Q1: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Initial row permutation, P1: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 1 + 4 : 4 + permutation vector OK + + Symbolic object: OK + + +Get the contents of the Symbolic object for C: +(compare with umfpack_zl_report_symbolic output, above) +From the Symbolic object, C is of dimension 5-by-5 + with nz = 12, number of fronts = 1, + number of frontal matrix chains = 1 + +Pivot columns in each front, and parent of each front: + Front 0: parent front: -1 number of pivot cols: 3 + 0-th pivot column is column 3 in original matrix + 1-th pivot column is column 2 in original matrix + 2-th pivot column is column 0 in original matrix + +Note that the column ordering, above, will be refined +in the numeric factorization below. The assignment of pivot +columns to frontal matrices will always remain unchanged. + +Total number of pivot columns in frontal matrices: 3 + +Frontal matrix chains: + Frontal matrices 0 to 0 are factorized in a single + working array of size 3-by-3 + +Numeric factorization of C: Numeric object: + n_row: 5 n_col: 5 + relative pivot tolerance used: 0.1 + relative symmetric pivot tolerance used: 0.001 + matrix scaled: yes (divided each row by sum abs value in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + initial allocation parameter used: 0.7 + frontal matrix allocation parameter used: 0.5 + final total size of Numeric object (Units): 100 + final total size of Numeric object (MBytes): 0.0 + peak size of variable-size part (Units): 2528 + peak size of variable-size part (MBytes): 0.0 + largest actual frontal matrix size: 4 + memory defragmentations: 1 + memory reallocations: 1 + costly memory reallocations: 0 + entries in compressed pattern (L and U): 2 + number of nonzeros in L (excl diag): 3 + number of entries stored in L (excl diag): 2 + number of nonzeros in U (excl diag): 5 + number of entries stored in U (excl diag): 2 + factorization floating-point operations: 34 + number of nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.40964e-01 + max abs. value on diagonal of U: 9.13625e-01 + reciprocal condition number estimate: 2.64e-01 + +Scale factors applied via multiplication +Scale factors, Rs: dense vector, n = 5. + 0 : (0.196078) + 1 : (0.0319489) + 2 : (0.0133869) + 3 : (0.030303) + 4 : (0.013089) + dense vector OK + + +P: row permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: column permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +L in Numeric object, in column-oriented compressed-pattern form: + Diagonal entries are all equal to 1.0 (not stored) + + column 0: length 0. + + column 1: length 1. + row 4 : (0.240091 + 0.0591529i) + + column 2: add 1 entries. length 1. Start of Lchain. + row 4 : (0.847284 + 0.423642i) + + column 3: length 1. + row 4 : (0.659838 - 0.0126577i) + + column 4: length 0. Start of Lchain. + + +U in Numeric object, in row-oriented compressed-pattern form: + Diagonal is stored separately. + + row 4: length 0. End of Uchain. + + row 3: length 1. End of Uchain. + col 4 : (0.510471 + 0i) + + row 2: length 1. + col 4 : (0.392157 - 0.0196078i) + + row 1: length 0. End of Uchain. + + row 1: length 0. + + row 0: length 3. + col 1 : (0.200803 + 0.00267738i) + col 3 : (0.240964 - 0.00401606i) + col 4 : (0.307898 - 0.00267738i) + + +diagonal of U: dense vector, n = 5. + 0 : (0.240964 + 0i) + 1 : (0.909091 - 0.0909091i) + 2 : (0.392157 - 0.196078i) + 3 : (0.484293 - 0.0052356i) + 4 : (-0.677403 - 0.143059i) + dense vector OK + + Numeric object: OK + + +L (lower triangular factor of C): row-form matrix, n_row 5 n_col 5, nz = 8. + + row 0: start: 0 end: 0 entries: 1 + column 0 : (1 + 0i) + + row 1: start: 1 end: 1 entries: 1 + column 1 : (1 + 0i) + + row 2: start: 2 end: 2 entries: 1 + column 2 : (1 + 0i) + + row 3: start: 3 end: 3 entries: 1 + column 3 : (1 + 0i) + + row 4: start: 4 end: 7 entries: 4 + column 1 : (0.240091 + 0.0591529i) + column 2 : (0.847284 + 0.423642i) + column 3 : (0.659838 - 0.0126577i) + column 4 : (1 + 0i) + row-form matrix OK + + +U (upper triangular factor of C): column-form matrix, n_row 5 n_col 5, nz = 10. + + column 0: start: 0 end: 0 entries: 1 + row 0 : (0.240964 + 0i) + + column 1: start: 1 end: 2 entries: 2 + row 0 : (0.200803 + 0.00267738i) + row 1 : (0.909091 - 0.0909091i) + + column 2: start: 3 end: 3 entries: 1 + row 2 : (0.392157 - 0.196078i) + + column 3: start: 4 end: 5 entries: 2 + row 0 : (0.240964 - 0.00401606i) + row 3 : (0.484293 - 0.0052356i) + + column 4: start: 6 end: 9 entries: 4 + row 0 : (0.307898 - 0.00267738i) + row 2 : (0.392157 - 0.0196078i) + row 3 : (0.510471 + 0i) + row 4 : (-0.677403 - 0.143059i) + column-form matrix OK + + +P: permutation vector, n = 5. + 0 : 2 + 1 : 3 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Q: permutation vector, n = 5. + 0 : 3 + 1 : 2 + 2 : 0 + 3 : 4 + 4 : 1 + permutation vector OK + + +Scale factors: row i of A is to be multiplied by the ith scale factor +0: 0.196078 +1: 0.0319489 +2: 0.0133869 +3: 0.030303 +4: 0.013089 + +Converting L to triplet form, and printing it: + +L, in triplet form: triplet-form matrix, n_row = 5, n_col = 5 nz = 8. + 0 : 0 0 (1 + 0i) + 1 : 1 1 (1 + 0i) + 2 : 2 2 (1 + 0i) + 3 : 3 3 (1 + 0i) + 4 : 4 1 (0.240091 + 0.0591529i) + 5 : 4 2 (0.847284 + 0.423642i) + 6 : 4 3 (0.659838 - 0.0126577i) + 7 : 4 4 (1 + 0i) + triplet-form matrix OK + + +Saving numeric object: + +Freeing numeric object: + +Loading numeric object: + +Done loading numeric object + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 85 80 94% + peak size (Units) 2543 2528 99% + final size (Units) 26 22 85% + Numeric final size (Units) 107 101 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2738 2723 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.41e-01 + max abs. value on diagonal of U: 9.14e-01 + estimate of reciprocal of condition number: 2.64e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 8.89e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.6552e-15 + + +Solving C'x=b again, using umfpack_zl_wsolve instead: + +UMFPACK V4.4 (Jan. 28, 2005), Info: + matrix entry defined as: double complex + Int (generic integer) defined as: long + BLAS library used: none. UMFPACK will be slow. + MATLAB: no. + CPU timer: POSIX times ( ) routine. + number of rows in matrix A: 5 + number of columns in matrix A: 5 + entries in matrix A: 12 + memory usage reported in: 8-byte Units + size of int: 4 bytes + size of long: 4 bytes + size of pointer: 4 bytes + size of numerical entry: 16 bytes + + strategy used: unsymmetric + ordering used: colamd on A + modify Q during factorization: yes + prefer diagonal pivoting: no + pivots with zero Markowitz cost: 2 + submatrix S after removing zero-cost pivots: + number of "dense" rows: 0 + number of "dense" columns: 0 + number of empty rows: 0 + number of empty columns 0 + submatrix S square and diagonal preserved + pattern of square submatrix S: + number rows and columns 3 + symmetry of nonzero pattern: 1.000000 + nz in S+S' (excl. diagonal): 4 + nz on diagonal of matrix S: 2 + fraction of nz on diagonal: 0.666667 + 2-by-2 pivoting to place large entries on diagonal: + # of small diagonal entries of S: 1 + # unmatched: 0 + symmetry of P2*S: 0.000000 + nz in P2*S+(P2*S)' (excl. diag.): 6 + nz on diagonal of P2*S: 3 + fraction of nz on diag of P2*S: 1.000000 + symbolic factorization defragmentations: 0 + symbolic memory usage (Units): 144 + symbolic memory usage (MBytes): 0.0 + Symbolic size (Units): 45 + Symbolic size (MBytes): 0 + symbolic factorization CPU time (sec): 0.00 + symbolic factorization wallclock time(sec): 0.00 + + matrix scaled: yes (divided each row by sum of abs values in each row) + minimum sum (abs (rows of A)): 5.10000e+00 + maximum sum (abs (rows of A)): 7.64000e+01 + + symbolic/numeric factorization: upper bound actual % + variable-sized part of Numeric object: + initial size (Units) 85 80 94% + peak size (Units) 2543 2528 99% + final size (Units) 26 22 85% + Numeric final size (Units) 107 101 94% + Numeric final size (MBytes) 0.0 0.0 94% + peak memory usage (Units) 2738 2723 99% + peak memory usage (MBytes) 0.0 0.0 99% + numeric factorization flops 6.70000e+01 3.40000e+01 51% + nz in L (incl diagonal) 9 8 89% + nz in U (incl diagonal) 11 10 91% + nz in L+U (incl diagonal) 15 13 87% + largest front (# entries) 9 4 44% + largest # rows in front 3 2 67% + largest # columns in front 3 2 67% + + initial allocation ratio used: 0.7 + # of forced updates due to frontal growth: 0 + nz in L (incl diagonal), if none dropped 8 + nz in U (incl diagonal), if none dropped 10 + number of small entries dropped 0 + nonzeros on diagonal of U: 5 + min abs. value on diagonal of U: 2.41e-01 + max abs. value on diagonal of U: 9.14e-01 + estimate of reciprocal of condition number: 2.64e-01 + indices in compressed pattern: 2 + numerical values stored in Numeric object: 9 + numeric factorization defragmentations: 1 + numeric factorization reallocations: 1 + costly numeric factorization reallocations: 0 + numeric factorization CPU time (sec): 0.00 + numeric factorization wallclock time (sec): 0.00 + symbolic + numeric CPU time (sec): 0.00 + symbolic + numeric wall clock time (sec): 0.00 + + solve flops: 4.80000e+02 + iterative refinement steps taken: 0 + iterative refinement steps attempted: 0 + sparse backward error omega1: 8.89e-17 + sparse backward error omega2: 0.00e+00 + solve CPU time (sec): 0.00 + solve wall clock time (sec): 0.00 + + total symbolic + numeric + solve flops: 5.14000e+02 + total symbolic + numeric + solve CPU time: 0.00 + total symbolic+numeric+solve wall clock time: 0.00 + + +x (solution of C'x=b): dense vector, n = 5. + 0 : (7.56307 - 3.68974i) + 1 : (-0.831991 + 0.0627998i) + 2 : (0.166667 + 0i) + 3 : (-0.00206892 - 0.107735i) + 4 : (0.658245 + 0.0407649i) + dense vector OK + +maxnorm of residual: 5.6552e-15 + + +umfpack_zl_demo complete. +Total time: 0.00 seconds (CPU time), 0.01 seconds (wallclock time) diff --git a/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.sed b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.sed new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Demo/umfpack_zl_demo.sed @@ -0,0 +1,7 @@ +/::/d +1,$s/_xx_/_zl_/g +1,$s/Int/long/g +1,$s/WSIZE/10/ +/define ABS/ { + s/ABS/ABS(x,z) ((x) >= 0 ? (x) : -(x)) + ((z) >= 0 ? (z) : -(z))/ + } diff --git a/liboctave/UMFPACK/UMFPACK/Doc/ChangeLog b/liboctave/UMFPACK/UMFPACK/Doc/ChangeLog new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/ChangeLog @@ -0,0 +1,385 @@ +Jan. 28, 2005: v4.4 released + + * bug fix: when Qinit is provided to umfpack_*_qsymbolic, + only the symmetric and unsymmetric strategies are now permitted. + The auto and 2-by-2 strategies are not allowed. In v4.3 and + earlier, providing Qinit and requesting the symmetric strategy + did not always work (you got the unsymmetric strategy instead). + This does not affect umfpack_*_symbolic, which computes its own + ordering and can use all 4 strategies (auto, symmetric, unsymmetric, + and 2-by-2). + + * umfpack_get_determinant added. + + * packed complex case added for all routines (previously only used in + umfpack_report_vector). This allows arrays of ANSI C/C++ complex + type to be passed directly to UMFPACK. + + * added umf_multicomple.c to assist in the compilation of UMFPACK + in Microsoft Visual Studio, which does not have the required + flexibility of the Unix "make" command. + + * local variable declarations reordered to encourage double-word + alignment of double's and Entry's, for better performance. + + * note that with the exception of the behavior when a user-provided + ordering is passed to umfpack_*_qsymbolic, versions 4.1 through 4.4 + have comparable performance (ordering quality, memory usage, + and run time). v4.1 is much better than v4.0 in performance. + +Jan. 11, 2005: v4.3.1 released + + * bug fix in umf_solve. This bug is only the 4th one found in the C + versions of UMFPACK to date (Version 3.0 to 4.3.1, from March 2001 to + Jan. 2005, excluding workarounds for quirky compilers). No bugs have + been reported in the last Fortran version of UMFPACK (MA38, or UMFPACK + V2.2.1) since its release in Jan. 1998. + + In Version 4.3, a bug in umf_solve caused iterative refinement + to be disabled when solving A'x=b or A.'x=b after factorizing A. + Modified the umfpack mexFunction to factorize A and then solve A'x=b + when performing the operation x=b/A (as "umfpack(b,'/',A). Note that + this has no effect on the use of UMFPACK in MATLAB itself, since MATLAB + does not use the umfpack mexFunction for x=b/A. When computing x=b/A, + MATLAB factorizes A' and computes x=(A'\b')' instead. The following + source code files changed: + + UMFPACK/MATLAB/umfpackmex.c (see above) + UMFPACK/Source/umf_solve.c (see source code: 2 lines changed) + UMFPACK/Include/umfpack.h (version and date changed) + UMFPACK/MATLAB/umfpack_test.m (new file) + +Jan. 16, 2004: v4.3 released. + + * user interface of v4.3 is upwardly-compatible with v4.2 and v4.1. + No bugs found in v4.1 (except for one workaround for an old compiler). + These changes add features only. + + * Note that v4.0 has a bug in umf_scale_column.c. The bug was patched + in that version on Jan. 12, 2004. The bug does not appear in v4.1 + and later. The bug is thus present in MATLAB 6.5, but it occurs + very rarely, fortunately. It can occur when dividing a nonzero entry + in the pivot column by the pivot value results in an underflow. + + * added to umfpackmex.c, for DBL_EPSILON. Some non-standard + compilers (Microsoft Visual C++) require this. + + * #pragma added to umf_analyze.c, as a workaround around a bug in an + old Intel compiler. + + * mexFunction interface to MATLAB modified. Call to mexCallMATLAB removed, + which can be slow. In V4.1 it was used only to get MATLAB's + spparms ('spumoni') value. + + * The AMD mexFunction was also modified in the same way (v1.1), with + the call to mexCallMATLAB removed. Note that UMFPACK v4.1 through + v4.3 can use either AMD v1.0 or AMD v1.1. + + * -DNO_DIVIDE_BY_ZERO option added. If this non-default option is enabled + at compile time, and if the pivot value is zero, then no division + occurs (zeros on the diagonal of U are treated as if they were equal + to one). By default, the division by zero does occur. + + * -DNO_TIMER option added. If this non-default option is enabled at + compile time, then no timers (times ( ), clock ( ), getrusage ( )) + are used. + +V4.2: A special release for COMSOL, Inc., only (FEMLAB) + + * drop tolerance added. A few new parameters in the Control array are used, + and a few new Info entries. + +May 6, 2003: V4.1 released. + + * No bugs were found in the prior version, Version 4.0. New features + added only. Major changes throughout the code. User interface + nearly unchanged, however. + + * Version 4.1 is upward-compatible with Version 4.0. The calling + sequence of some user-callable routines in Version 4.0 have changed + in this version. The routines umfpack_*_symbolic, umfpack_*_qsymbolic, + umfpack_*_get_symbolic, and umfpack_*_get_numeric have new arguments + added to them. The new arguments are optional. If you want to use + a calling sequence similar to v4.0, simply pass NULL pointers in + place of the new arguments. There are two new timing routines, + umfpack_tic and umfpack_toc. A new user-callable routine, + umfpack_*_scale, has been added. + + * "auto", "unsymmetric", "symmetric", and "2-by-2" strategies added. + The symmetric strategy uses AMD on A+A' as the column preordering, + followed by a postorder of the assembly tree of A+A'. Column ordering + refinement is turned off, and diagonal entries are prefered as pivots. + V4.0 only had the unsymmetric strategy. The 2-by-2 strategy does row + permutations and attempts to find a zero-free diagonal while at the + same time maintaining structural symmetry, and then uses the + symmetric strategy on the permuted matrix. + + * row-scaling added. The default is to divide each row by the sum of + the absolute values of each row. Other options are no scaling, + and to divide each row by the max abs value in each row. + + * Matrices with upper bound memory usage greater than the maximum integer + (2GB for 32-bit int's) can now be factorized (assuming the actual + memory usage is still less than the maximum integer). With this change, + the UMFPACK_ERROR_problem_too_large error code is no longer returned. + + * The current frontal matrix (Work->Fx) is no longer allocated as a + static size, via malloc. It can grow and shrink, and is allocated + from Numeric->Memory. + + * The AMD (Version 1.0) package is now required. It is available + separately. To compile UMFPACK, it must appear as ../AMD if you are + in the main UMFPACK directory. + + * The UMFPACK mexFunction now uses the internal utMalloc, utRealloc, + and utFree routines, by default (except on Windows). + + * Three control parameters for modifying relaxed amalgamation removed. + These values are now fixed at compile-time. + + * Many new statistics added to Info, and new control parameters added. + + * The umfpack mexFunction now returns permutation matrices for P and Q, + not permutation vectors. It also returns the scale factors as a + diagonal matrix. The factorization is now L*U = P*(R\A)*Q. + + * Option added for controlling the initial allocation of the workspace for + the current frontal matrix. + + * pivot tolerance of zero treated differently. symmetric pivot tolerance + added. + + * Makefile and GNUmakefile changed. umf_* routines with no double or + complex values are now compiled just twice (int and long versions) + rather than 4 times. + + * New routines added to save and load the Numeric and Symbolic objects + to/from binary files. + + * Simple Fortran interface added. + +Apr 11, 2002: + + * Version 4.0 released. + + * bug fix: the Microsoft compiler doesn't handle NaN's properly. + utIsNaN, and other ut* routines, added for MathWorks version + to handle this properly. + +Apr 1, 2002: + + * bug fix: if a column was all NaN's, then UMFPACK would fail + to find a pivot row. umf_row_search.c and umf_internal.h + modified to fix this problem. + +Mar 9, 2002: V4.0beta released + + * Map argument added to umfpack_*_triplet_to_col. New files + (umf_triplet.[ch]) added. + * minor changes made so that UMFPACK can be compiled with g++ + * additional error checking added to umfpack_*_numeric, for + detecting more changes in pattern (Ap, Ai) since last + call to umfpack_*_symbolic + +Feb 21, 2002: + + * User Guide explains the Makefile vs. GNUmakefile + + * umf_config.h modified, so that the complex SCSL C-BLAS uses + (void *) arguments instead of (scsl_zomplex *). gcc generates + some spurious warnings (cc doesn't complain). Affects the SGI + IRIX only. + + * ported to Compaq Alpha + +Feb 20, 2002: V4.0 (alpha) released. + + * V4.0 not yet ported to the Compaq Alpha (V3.2 was ported). + +Feb 6 to Feb 19, 2002: + + * Relaxed restrictions on sizes of arrays for umfpack_*_transpose and + umfpack_*_triplet_to_col. Size of "max(n,nz)" now just size nz. + + * workspace for umfpack_*_wsolve increased in size. + + * two user arrays for umfpack_*_get_symbolic increased in size, + by 1 (Chain_maxrows, Chain_maxcols). + + * lu_normest.m added. + +Jan 18 to Feb 5, 2002: + + * The matrix A can be complex, singular, and/or rectangular. + The solve step that uses the LU factors can only handle + matrices that are complex or real, singuluar or non-singular, + and *** square ***, however. + + * Estimate of the condition number computed: + (min (abs (diag (U))) / (max (abs (diag (U))))) + + * Forward/backsolves can solve with A.' as well as A'. + + * char * arguments removed from user-callable routines to make it + easier for Fortran to call UMFPACK. No Fortran interface is (yet) + provided, however. + + The solve codes for umfpack_*_*solve changed to #define'd + integers: + + UMFPACK_A Ax=b + UMFPACK_At A'x=b + UMFPACK_Aat A.'x=b + UMFPACK_Pt_L P'Lx=b + UMFPACK_L Lx=b + UMFPACK_Lt_P L'Px=b + UMFPACK_Lat_P L.'Px=b + UMFPACK_Lt L'x=b + UMFPACK_U_Qt UQ'x=b + UMFPACK_U Ux=b + UMFPACK_Q_Ut QU'x=b + UMFPACK_Q_Uat QU.'x=b + UMFPACK_Ut U'x=b + UMFPACK_Uat U.'x=b + + All arguments are now either int, long scalars (pass by value), + or int, long, double arrays (pass by reference), or void * pointers + (pass by value or reference). A void * pointer is of size 32 or 64 + bits on most machines. There is no need for the caller (C or Fortran) + to dereference the void * pointers, so these can be treated as + integer*4 or integer*8 in Fortran. A Fortran interface would have to + have all arguments passed by reference. + + * All user-callable routine names changed. The four sets are now: + umfpack_di_* real (double precision), int's as integers + umfpack_dl_* real (double precision), longs's as integers + umfpack_zi_* real (double precision), int's as integers + umfpack_zl_* real (double precision), longs's as integers + + * Ptree (row preordering) and info on pivotal rows for each front + added to Symbolic object (extracted by umfpack_*_get_symbolic). + Ptree added as output argument to "umfpack (A, 'symbolic')" + mexFunction. + + * umfpack_*_transpose can do A' or A.' + + * umfpack_wsolve.c file removed (now generated from umfpack_solve.c). + + * Can now extract just the diagonal of U with umfpack_*_get_numeric, + without having to extract the entire matrix U. + + * UMFPACK_ERROR_singular_matrix (-2) removed. + + * UMFPACK_WARNING_singular_matrix (1) added. + + * Control [UMFPACK_PIVOT_OPTION] removed. No longer any symmetric + pivot option (conflicts with the handling of singular and + rectangular matrices). + + * Iterative refinement can do Ax=b, A'x=b, or A.'x=b. + + * Most floating-point operations done in macros, to support the complex + versions. + + * Info [UMFPACK_N] is now Info [UMFPACK_NROW] + + * Info [UMFPACK_NCOL], Info [UMFPACK_UDIAG_NZ], Info [UMFPACK_UDIAG_NZ] + added. + + * umfpack_* routines with "n" as input now use two arguments, + n_row and n_col. + + * umfpack mexFunction now explicitly transposes A for b/A. It computes + it using the array transpose as (A.'\b.').' + +January 1, 2002: UMFPACK Version 3.2 released. Submitted to ACM Trans. + on Mathematical Software. + + * The umfpack mexFunction now returns the Info array when the matrix + is singular. Returned an empty array prior to this change. + + * Renamed variable that conflicted with system library routines + (system and j1). + + * Added a #ifdef MATHWORKS definition, so the built-in UMFPACK routine + (in a future release of MATLAB) can use the internal ut* memory + allocation routines, ut* assertion routine, and utPrintf. + + * MAX and MIN are not defined if they are already defined. + + * A bug fix in umf_kernel_init (a variable was not properly initialized). + + * Removed unused variables. + +October 8, 2001: UMFPACK Version 3.1 released. + +August-October, 2001: + + * added umfpack_btf M-file. + + * modified the BLAS update in the frontal matrix. If there are only + a few pivots in remaining in the current front, then the BLAS3 update + is delayed to include pivots in the next front. + + * Removed the special-case handling of dense columns from the numerical + factorization (kept it in the colamd preordering). This improves the + performance of UMFPACK on dense matrices by a factor of 5 or so, and + simplifies the code. + + * Added a symmetric-preference pivoting option. The option slightly + (but uniformly) improves the ordering when factorizing matrices with + symmetric nonzero pattern. That class of matrix is better handled by + the symmetric-pattern multifrontal method (MA41 in the Harwell + Subroutine Library), however. + + * Fixed the detection of integer overflow. The 32-bit version cannot + make use of more than 2GB of main memory (use the 64-bit version + in that case, instead). The 32-bit version did not correctly detect + when it was trying to factorize too large of a matrix. + +May 4, 2001: + + * SGI port extended. It can now call the SCSL Scientific Library, with + 64-bit BLAS. Make.sgi and umf_config.h modified. + +April 30, 2001: UMFPACK Version 3.0 released. Changes since 3.0Beta release: + + * Long integer version added (umfpack_l_* user-callable routines). + + * Peak memory usage in the numerical factorization reduced by a total of + 12n integers (8n temporary workspace used during numerical factorization, + and 4n for the permanent LU factors which was allocated + at the beginning of factorization). + + * Ported to the IBM RS 6000 and Compaq Alpha, with help from Anshul Gupta + and Friedrich Grund, respectively. + + * 64-bit version added. Uses dgemm_64, dgemv_64, and dger_64 in the Sun + Performance Library. 64-bit versions with the BLAS might not work on + any other platform, because they take int's as their integer input + arguments instead of long's. Unfortunately, the proposed ANSI + definition of the C-BLAS also uses int's as input integer arguments. + It ought to use long's, or include a version that uses long's, just + like the Sun Performance Library BLAS. + + * Additional statistics returned in Info: + Info [UMFPACK_SIZE_OF_INT] sizeof (int) + Info [UMFPACK_SIZE_OF_LONG] sizeof (long) + Info [UMFPACK_SIZE_OF_POINTER] sizeof (void *) + Info [UMFPACK_SIZE_OF_ENTRY] (was Info [UMFPACK_WORD]) + Info [UMFPACK_MAX_FRONT_SIZE_ESTIMATE] est. front matrix size + Info [UMFPACK_MAX_FRONT_SIZE] actual max frontal matrix size. + Contents of Info rearranged. + + * UMFPACK_ERROR_bad_configurution error code replaced with + UMFPACK_ERROR_problem_too_large error code. The "bad configuration" + error occured when sizeof (int) < sizeof (size_t). Now, the int + version of UMFPACK can use 32-bit int's and 64-bit pointers, and the + long version can use 64-bit long's and 64-bit pointers. Both versions + check to see if the array sizes allocated are larger than what can be + accessed by an integer index variable (int or long, depending on the + version), and returns UMFPACK_ERROR_problem_too_large if they become + too large. + +March 15, 2001: UMFPACK Version 3.0Beta released. + diff --git a/liboctave/UMFPACK/UMFPACK/Doc/License b/liboctave/UMFPACK/UMFPACK/Doc/License new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/License @@ -0,0 +1,53 @@ +UMFPACK Version 4.4 (Jan. 28, 2005), Copyright (c) 2005 by Timothy A. +Davis. All Rights Reserved. + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: + + http://www.cise.ufl.edu/research/sparse/umfpack + +-------------------------------------------------------------------------------- + +AMD Version 1.1 (Jan. 10, 2004), Copyright (c) 2004 by Timothy A. +Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +AMD License: + + Your use or distribution of AMD or any modified version of + AMD implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses AMD or any modified version of AMD code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: + + http://www.cise.ufl.edu/research/sparse/amd diff --git a/liboctave/UMFPACK/UMFPACK/Doc/Makefile b/liboctave/UMFPACK/UMFPACK/Doc/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/Makefile @@ -0,0 +1,56 @@ +#------------------------------------------------------------------------------- +# UMFPACK Makefile for compiling on Unix systems (for GNU or original make) +#------------------------------------------------------------------------------- + +# UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +# All Rights Reserved. See ../Doc/License for License. + +all: dist + +include ../Make/Make.include + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +# Note that UserGuide.tex is created from UserGuide.stex, the files in +# the ../Include directory, and the ../Demo/umfpack_simple.c file. +purge: clean + - $(RM) *.aux *.bbl *.blg *.log *.toc + - $(RM) UserGuide.tex + +#------------------------------------------------------------------------------- +# Create the User Guide and Quick Start Guide +#------------------------------------------------------------------------------- + +UMFPACK = umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ + umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ + umfpack_get_determinant \ + umfpack_get_symbolic umfpack_numeric umfpack_qsymbolic \ + umfpack_report_control umfpack_report_info umfpack_report_matrix \ + umfpack_report_numeric umfpack_report_perm umfpack_report_status \ + umfpack_report_symbolic umfpack_report_triplet \ + umfpack_report_vector umfpack_solve umfpack_symbolic \ + umfpack_transpose umfpack_triplet_to_col umfpack_scale + +UMFPACKW = umfpack_wsolve + +USER = $(UMFPACKW) $(UMFPACK) + +SRC = $(addprefix ../Include/, $(addsuffix .h,$(USER))) ../Demo/umfpack_simple.c + +UserGuide.pdf: UserGuide.stex UserGuide.sed1 UserGuide.sed2 $(SRC) + sed -f UserGuide.sed1 < UserGuide.stex | sed -f UserGuide.sed2 \ + | expand -8 > UserGuide.tex + pdflatex UserGuide + bibtex UserGuide + pdflatex UserGuide + pdflatex UserGuide + +QuickStart.pdf: QuickStart.tex + pdflatex QuickStart + pdflatex QuickStart + +dist: QuickStart.pdf UserGuide.pdf + - $(RM) *.aux *.bbl *.blg *.log *.toc + - $(RM) UserGuide.tex diff --git a/liboctave/UMFPACK/UMFPACK/Doc/QuickStart.pdf b/liboctave/UMFPACK/UMFPACK/Doc/QuickStart.pdf new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..db89a759ad9db3b97f37c99ff737ea9bb779c66e GIT binary patch literal 137498 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
ItN?$znE(A50sgOs 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 z zXT~XdkGYWRMcOGTAzx5Cua}^>CqkHiH+1WPwhn*h^CN2HQz2AH?g#ltsrP97!J$Z4 zz?wOMAInx_8>zS|@$TX3nQlg>RRmzd;x8;0qzYqC3}2HjJGCOird91ZdADAOM{xHL zS6`E6Y)#|Ai&7@SC9b|sqwN&w)Fc@?UAmTK8OJ;_9Q@v_uLEigyNfdd6yiz$Yk*OvBwSg@=8;S zaQlec9_@U6J8#rZP4E}=m^>?+>TrPH@+YUFNt}QyYE+c?Dw&nMv$Z;VBdPP((oSho zg50&pGPC#Pc;DC9bS`~xF%9f_Bqf22XJ-T|*~%IC)`a_PiWodN0T;K8lfOTfBvMh-FVZQ?!iH6xJ(1enAZ!#8UaM#e7|<>`HrQdRKGZ85qW&V zr(ilvV>~2#`)R zR<_Il7OO~|c+Uc=FMypMnGFV3zPi@Ncb9e_nlkhBpiO~k*CFF=E6O$}{#-L++-p>lg%%E2i8ajQ2DV^0KrWu48vr){} z+rW)kn3E+|41DKw=&oyWY36Kz?K0#1tz6^%LIe8?T*lb5a4&28H!Bq>(+>-C!0wn& zn)cHRy2Au29T*BZ1jXn&uc(uO12R{M&Y&;WFU4YF@jA}+mH0R1sCZL4oS3lTGDX_b z;YFV^N{$Wg-yr~8P`W!|uOS$QF6g7Za5 z9m|!}fRjXU!nEj*4HL+i4k!N~(#|nRmTp_uZQHhO+qP}nwryLht<|=<+V*PO_TAri zv~|wi=iVP#IcwI;nj<1BGNK}$@x1;lMLRY>XtixoR1?!yEWmW*hL*-}H{Vlx4f(w+ zs^qkAS|kQsa2@+e1-^q0f{|u82y~VVtwy=>=<~*xE9q4wYHIFh`Afg;WHsQs$4(E2NXyNDer7oroTADnO>ke2>Y=})Vt<@$#2;&NQVsB5 z!3E`9WiD~_;u^JhE=BWo&-j}t+-v%NN3PcSF*H&R@@m@BGqkE%qo36f>s=S8STM_X zFPvJ!h12echwDF`k%mo7qQ@b*>ex^QIfd?ZWb3{OCEAI;-Dm>D=_2{AjsPZGzQr*g zi2Dxj9T=fEE1Rmuwa=NLdG3q0C_PP9P0vtxJ}(}LqfuXME=f}j#r5m;dIPeAQO78u z1{_snlE~6g*~%`lveI$ng8>lQ`3DtoMTeh$W(2&EEQPbOi)IuGt>swk zM;4-sXa|HE3^Z;cQ+4L$t>Uu60f}0R1Sm<%>oab>Qq(Hm=IHS2{nMY0#Pd1+?PG9D zr#N#$m?rD|Vjp1fE#OBn?fQP&};#R~N`BHG5<5E@NCUiyR%>7aoTShtD87M`=&r~}5XHba;t_49`@nLYwLX54TX1EPz;Bt(wO%j4-Cr_M#<*}o( zn$i1mZ#k-F0WKNUMn}1j+52F>DAulHrpFPNM^)kUX4*2=leqazkyjo;UMKpejx}@} zGV~kM(^SY1lxt#hUE?S74iBgSjGl>W@0$^~`=KtWIXmlkm0&9Uo>AvQnB3rt$C&cL zF4g+ps};~|`n7Gel`rafUH9Tib!#Hcn-;@}TAqz9XvEw2ZLu?%7xC_{WIb#j$bggl zqv|h5)tzPKJJ`m*9w?4Pbh*(=8^k=;%Qh3E(#)cJaXvnP?J%eeh|dhPYy6;sCECVj zq5yifAF@8;*v8c2r1{+^7Sh)vm`@!IJl(&&D_MSiObJDfVB5&f1j~n56QKBC=em0xx=8_0z??M6C6MY8QVhO=Qh;Fe2t0cXCrs zo_BKjFxt)weYyXrajH`oFW!QA4HHgmaxN^@Xcw@=x3H%n|6w2$D&^7O&E2Pz-b9X7 ziS5vuf2wlH$->z332Uwb;Qq`zVQmoU;R@zyH?2{FVhEg?e8m+yA<3A&Cf!j!}ZBI#S9 z+*Ag2tCR65!Uo*;??;Bjvzu>})8GsKb)Wb+Rl>f8wN$f(;3G6jb|71q%VUEseb@72 z-vFr6y;B73^BX$BC|zM`#|fCccY|N29=XOaZ6wQ+2O|+4=djIzw47E0DH8o?EKg^Z zcY^|ZZPuj`F&JiXDNLVP%I%O4=ydg*$=XB;+D{%oJ6jbA=%keKJH)N zD+elv*A>?`w}HRG8zv>x_HTgc(sM$i7ri=9uA;8|q>WqJ0i$sCtm#B-OkBJ_pHXBL zLs|7aOs2S)$R~#=F?oIsYSB_nQUV7;D>8*3amUe+)e3|(!a|0kWE*OUKg4K_0vr>! zNIp1;dv3pWYOWHQjBcBzv7gNI?=ju?EfP*&C%2!G6WufM#IZCt>=nZp9Dpe@1`Lsh zph2C-c`u0|{5 zy-3k@uuC0qPNBdGnQva}ZJ}+Mb2&s_{w}_S8?Da4bg7|GI;Uz}8x7JH_%#PLUFw+L zQx(z6X*-@tE^lQ68H?9pN>Wo%VWb)Cm&2x5X@p&#xLp8-WLZ13vwU9cMuW0kCkK0E zPXfvkRz{~nBm0>hj35phL27e_*07mF%(NfG{d|3sgHtL$VljhYJWCbG+ns?9;)Ix7Tx1H=z)3| zbmhh|H}vVFpLb@&=7gtKI2~B~iiV5lF|i8?f_c4wra}0Al#FR<7PCydx>LV(xaf_>=R+-NQ*4_{<*I1HUC7x2u_n!pK+FwY=;q@il5_J%^u8-GX(o z9!-5qx3+AUbLpaAq^q&vd5Z?^qim^#08+hck3IPe0t1pyUNx~?52v1I7Xt3HM{QSx z={-SyDJC+ozM+Zft)s=S%Z6z*J6QngJ_F-hRaT_Z?{}sxQC$4I>8*}=>7ezUzUV7- zm{P>H>CoFxj>UG+4Y-Ud#IdUhf~&jm>UjBjQ>)TlhAPw%2V4Dh*_3Qiu=lL|9zRuA zHl)dR)Ew?;=XGoNfuQ@T`YQ8okH?On)@^l8vUDcZB|5g0JFB8yTiZI+7<~Gl^c0B7 zVd#>vD2gAl9k4&0p5eJnp%i&`hkSz51`>?x?tW_)WXJl%*#TX*^Sp^A5>E|E0;p*= zqfEn>?$6q&w^oJ?~)-E8Lz zcC9>3izOlHE=>A;L+dwJXN2~`P09GMy&grmxfA+Ky2P-yT!6`O5iUpd4kQ<`RXe3H`np+?G=Z)>G3gExVS=BD3)TDTUan zRkPnvkxr@}?NfBlCG-xwFzn^Nn_&=$T0v)X*V0dAo0<(um=|x1`{Y_=IT`fhJq>ihe z&Z)H_xN+*xqmJ-1)Jug-^?CA{RY6kBr`DRnaJbZXv;z!7{qq%>pE9`Q%&Pr2QR(o@ z{wzie$$;lq!4K+p&mYlBI%b^!_)9jygr0dd+K8xq?%9QUAzx5n;UrUo;%M}x!FK@JQ{X? z*h=!3CqOUK%C)V1-d=PL=7M)p{4RZN+h$l;bqZlbx6IpS-aflrBK#7Xn#RouLf|i zR3nYvtS(3xp)EMZk-rAjrJ{r{RUI}`zPuk@weTzzUl;d_EYW_ywe$SVkJ0RkVgb*R z9BoIuNHriMVqaD+v8AZZX9xZINLG~wJEt6J#QSmCZS~D%nFOfwr`X4YTfOt8F1d1i zWUi{1we-?*xW0=+gl5`wrDDvr zDS&%WPSH+6>bfZ$0Yr*?g)@euvCXr19fDZ)9tmfa(~gGSU}g+S$R$hYDr}ja8C4%D z#Ju94Lni{1ZhT;mQ(aCKxO3#^@wo{P`@EbG(lx_vva5?AoqI# zO^Q15x1yZ1PS;u5E`N@X8kSh9IG?Aou0Ng^hP@g_@L2GW2~Bo5Q3 z*m`HOgSO7zeB%O)f=-s!aON)vFT+*4{3%@ zEP>bSsgGUvJr>G%_6!!33*TtBPgH8;oiHzR8y<~V%Y{(XWy4%E{SV?uV2WEk0e zi8S||6fO$u`Yl@d3<7}DN#NHyM#ywTc_L1tQH&#-{ke8)6_fr9me}$U$6X=SxL018 z5B!3;gIq~TEaaqsP7B+qKb8|Bialjrwh@O2Cs}adou3wUHHJHg+riIL``Vpkwd4M& z{HRDqsf|+SDRUq{c16M_90l`uYzXLFH(;k{x-Yo_ab(`Nqznib&>#NnA%%Vh{0u~u zd!yI=a_ocVV{0(s&4Zf)YJ-fyUJqsmf0Qr-dkc4_0ir#WT`=Y2{8L~G@6jsn0CGY_ z3m72vY#8n@KSmXoYcYRJg*Ih8y?a|Uf8~0;_fKq8VdsUl>*-~RciO=Gfhfno95fgiyQA@TLLDN^@=9G>5bV|bsZD4JM}ACAx*T;d9p@d?JJ z&k|j^oXE)$R592jD=a!>df~p&Htp4MfNdX30LT-_+Lo~hMx&zmHof>Gg{2Yg*JJD% z)wVM|7yt{<3RPofbU2c2OvDf}vawwBb-;D(EGtjudIOtxqynR2p!lfeKyN7NrDIS+fh#A_Y}6t? z++cjp;6~5HKqTL4rmCBbVN4*+nPWA@TB*s{7kP+Ss$N@7s@|$6tExNj)cc{hxDsSEmT%q)#KqXyw*H|O!VK1Q zjXp=hyc5PWJHjo>IDI2Du{!GQ?9n`O%CZK6vSU{{I!}`*fCAW$waSqJLT zb93NGPg-`Kw0i}b18YG4NmiKK(}Ag2An6@0Kg3mr_HL=Q+Z73v;}l{wm^Q9L`QT9Z zbk*UMiaGb_P!gHl|7V{wZtbW89u&mXDf>N2!4uQn!?RrIBDF6MF;&>3y3C{mbxg|W z2>o`r6TjZ+(>j*i=~DS-mAJ_Rl@reElnfR|Uda4vKmuefEd)7xZY3h6oCEItw-D&S zA@_)XZFwdX-AVe>5(A9{)m2s))5&(#RP><7K}bdaLiAY8dBxaUpyWVo;0Z_RW|15& zyNsiaM=-o$@t860O0buu)2# zDPYE>;6<}&S4xjNbwm~r9)|6m#|#a|><&a*BTq!-(+jqG!ni(QvmYCi*Upo2I1ogO zRSxkL^^*kzOd2ykV2P#)Wp{uc5l%?QHKtc0@0L~2jo+~a^5f!9LK~=ZZFPwt2ZJrP zL#QD7Ul?*D?ig4QKoLqL!jU6SjGl^e+^C`85e&kJhSW!XL5edq>9ub6K2>qsl)k~f z@wDHy!xQ3*Tu^x2Gg6PtKxgBZgZ(GgUf(TN?eG+=o{2ORfS4C8Q=LUkp*EERP(ARV z)61?b*yoW!%wfe@nh;xiB2>^*+y^{xwYpdDh|XS8q%KW%!+qz6Q_mRuaVg7STl`k6 zyCTgUl!OyYBL+d!#-!x_M;tUoCmh?#@qKT-iKig;&jwVDcquqT*2Ar*I|c-RT}y0W z`p3(<=+JOC>dsrRF66!=?YiDaI78&H5&*1X6KS1(hW8_@LxWh@wJtO-41!%80lRSr z?E9@?vb~hb#7V37Zqi*o(u9}PM))_jegPR33s*-qBm?)yS_xWf;V1c{R6hoLP%Hxh zZ;dq~c;5Pn=e+j=5Rh|m#;Fe4e)nly&I~b@!d}a&|A>Kh#O=nP`Z2|}m4K))q|~th z@H7Wr%E#H9jGgg_`gHNdTDyxkkrTw)Ls>8`EuYfP0B!KHe zdlXkLfUYWX>p)lybi$Gp_k>uYaEXi*!UH1}yle1n8W3?TT!?)mRr5i38jdNI|e^UIR<&|&6iiz^2bxpUUY zC&3HltKfL?r3J0uZS^DuP|i18CId@Yt!J#AU$LlH%P{G$TZ^s%;Li^e_xH$ZVl-fo z6F4-l{f9P$OOUjCPo8>#q{^BJJM2DDi$TFT5KEiv`;xp1{MfGuK5zokSEQ?O>MyIBcfnVIme$THvXH4?GF!+)wtAJQR^bT<=*X34E$c9sGNb6;ke1Rz*t$(;e)gN%`YKKo4 z7~N4v|46uHA@gm+Jv1|NR_Q+}nhFSL%#`sytGzuN7*@<#!V^z-1Gscw9(8Qgt><&M zfc2aT*iIAiS@Fd0#Psm5LWC;Zd&@X#1lUo2cRH*I)kwsRZNA$>CFCUH1&T6OL;byB z?sguO41hk`>gxG>%C4tjeB}oL%#+kL2;^(U~h3wRY%dg<0Sx`xoXsY>x=wOdYLS@W#s>-pTH&hHY!N^iQ^KLC2Yg|!zaMD$%L3{UkDHUT(w!uQ?kS_z3YXbYRN%HCqtBYH@6&yS6BtyH zxR}bX99ga}>SzQl0#>j#2qC!Rm%Mxn>#v7B(B=FfXL_N5i`goR5Xlf$^#$D26VGZ8 zbYnGdG!yT^q66r_-+8HuuNpNeMX$k4#Yn`|c*cpBdA}8C5=BsMuAA`Si(v zT@#1ZwA+E}h(t|ZE|7%!hJcRgC0`^R)4hV{n=+iR{FOG!h!)F6Bj_`W1up{|Wug@U zzbzU+u zcx=i+wv#f1g!(2V)EYi=;VHHVm0|JBIJJ%0M z|J7nOG4^V0-a`fLm;mf0>C=G|?{0eS=!>Q>q}ZHtZqxl8L*@-D1|{G(s7}q&#<4;) z2w-hSlI$eiPvL@D6gzN3El#UXB5t$a`S*3!_kPGyFNdBjW7R=D&Fe3zP=$&)2YpjiiL};xc3NBjkI+a3#1-v>o#Tx;7O+~oyqJadq{q;?`0p_bWG%B^KUpLjl1WuaEaK)y^M5AzI;|miRvPJKjxU2DV(a%DGnILdC173T^f} z!Aj?3_zeyYv^XoJm1aYJn{PMh+E@VXQE4=#gJG#MunFLLVcQh*5~&P z@XI&y2R|d=7?{n)fswuSg$e8nJ@_dT?mxCA{6AP;|1pR8Z`%@>{;Ms4k>T~QS+ zl%z%fOh*1^Z3%yGdS&`2rq};X5cA({_fNws*!~C6E6X2A%&dQi8wofV{+sBEe;UF3 ze|M7pk2caj9i)GyAN^A-`j7t5zqW_|mpk+ibLijXB>%N4^#A4p{Vx;fpB~V^X^r>? zeJvxy-zOjcXPd&mlv4a3D;Ws>{(6SLdiVdAk^JB7{Lhk%|MmU;_qF`(?0+>}{B_#g ze>Pk&b1?mtHk5(szv;JN=U`+1m$jj(e`rIWuOTf@m7GrE3WZPQPU8YGoiYLowFQJa zuuDo26TuWu!7L?D6OcejW;UPi{q1;X?(cHckDbl7f4S>g*X`IZ>v`+bz|1^&nDjef zMxR$0T9sh(?Lh`00G@Ogbbnx;2}T)DCpooBs?~OL)-ud5FrH# zAq@z%(Exb1RnZU3ZTAEB(aqedCs7D2g9bS?f%XGr5x|2-KsScbLO{(1Z*U3m_;>;~ zDo_YK*P&hk=tgjZ?1BQ`?*Rn@)EC!)_kkH*Lku3iPbO0Rf`dc&RL8hDeY+OdLkQuX zM+v~SOacyQf(RQd=mB6Df=ic&j#~^O$o<%1c+4M85@g?|e9*5Tg z2f&T6hWi>=SRpvKU^V(gLs{q=d!oIpGyyr=G*-}HOpD?6|ka}777 z7``tiKRq8mLPo^z`*U)Se+b2}#i5=Uh7)0c2mk>H@NQUC4lF4I@Jk?o7zXARP{1c4 z?$yK40sa69ppi5XfSUv8x$Y7L3Fu~RKvze=KlB?F5$uNZrGrbrpjVg(fKUBkq`$vc zcn^S&1Lh7M`X2a&r)#$tGr|NMoYO%VK44u z(fbyoBO^fml)Vtu>X)#9UkS(yyvP&i9r)K$3O_={=?yrMDDJmFN##9$L`vvapoDJv z4ur_rz?VP?-3PqLS;rq!L--MkuHV3k8`rnsM7AD(nZnldCzua=winS;_Tl?uc)jzo zBQ7QfceOtgoCAdic<=xa7_>K*djS8jgA8jBXP1Yd3VP6YdmkMY@r~R3C_+HM5Z`-E zap3sDzQIWZPY<#O+%T-05xODO<1k?nRSuyU?yP?YE4D}#t1sQ3#C%G?p=*%kWgL{1%h5}!fXZL%?y^zSF1|_x?0_InmYJy-o z#X`+r{)#!RWmB-e_TPDEBq)=(L9gslb`2&URAO`z98N>w@>p5;7W$=JMfVzdrE)k4 zDt&Jj@pujX6kwht={Xu1v5DkEw*dRZ%VwT(8@V*hQ+?lll)iNFi#(;by%-frouFS5 zxy3Es;F89GQ8+_B*9acXPLJlosg`Y?J{5~Hx5QaYy~Zy7Ac0@mmPH(Dbp>R?X9Cp3 z$3<9dICfyzse-HwrziOpM!mh<1wCElEMHB&>Z(Ll6W#bOF!U1RX+|9+?po^jwc)TH zq@zJ!JEk0-B*G3VT$D_Xz046cG&hZpMTM#y(Uh>Fs9&9RM>?&OFyii?m~dbA(`v~> z6!A>o`oR^i3r=r+q59sr^piLE$cIEgcZz5~5hXEMDi!1jp1D_)d z#rH&V?ycm^5&Y7TmouG265{A}prus06h^q*2eQ7a8ryLD$Gf_Tyc2R=ry2%EV@j$4}y!^$W<^B`1M{~wPd8gDnlbX@Y>}$km zJ@Cmki-vd4>ki{n&kSw5R^ow|CmTErhj1hcw&q-yd+~{-J0q)tWWV)+#d$yCB79+} z{uFKqRI65Hp`i^WJ+ zZ+wEh?kCg|Yv}#BiPHWD-*&X+lZH4P69Ul@{%f;i!CjRMq>VvT7#Y}H7kX*h4sXJ& zf_P*Vnd`oBDT;c`Y@Muia=B;pTft}%&lz}6;X*=n!Dde%nfrSn>2txW=`3f*XN@MY zb4rZ$Pspn7D4VEsH)B5^TGO({NL(v&tnKXDIoEJsr@`D{)eiUkGax z7kH;V{>S+%dPNi#zLcLpVX*EnZKa(Zud3N~G*-e)eUerri+sb*>ZcY1@fYGmq# z_XS*&sVsLqF|4ldQ_Ab<74o!5+qRi7TVtInrN!Gx2L32~w_?m@^pfQ4QGBsx?2H7_ zfjsdSFHdVM!9rv@Bi;jsmmyH+ z?RMwo)~Z#2RK8B*Rf3mCvg6sGM!I^HYc=mA50&hVYRMWj$5$L&Ycv3!wyWeK6{>5+ zZq)2D8Xc6J2eHwo`K|O}Kqju+^v<@fSn1KVNd%*`0`q z7$~`wv8ssXa`_}bzK^af_=-xa>gZ|ar#bo9{V3{jJ&2MCQezvu)&JRC$5iM4@K9}N zNifDJtD%wDS4A=U>@)ywB(K7{xUQ&2siw1WCAj9<7(rgn{_=AOa-TYmH5Ua0Nh@hk zAqQZ6*e@R#6PBHP&K zXz|%mZULl;uORldc%w(7Q%&4zAbQ~9jUirfHOUy#sMn^J=Y}{`r)1O{E6X17aFBOm z3A0a6b^c=xf8vuTl6m2hjAcLEz!0b0u;hy&{c)6*Lr*-~jkz1svBXuj&f4PHu?&pN z6P#B=dtYQjFn!sws2)rIgSo=~lfn^}gCaZkf*+EO0yf#O7b!&%=o%JM2<0!0lOtMD zEmhU52<~L>go}4u)YWlQbFziync|$d!w7ojizYaZKOwoK#WFDDLsH-0y|jjFEZsk? z%YDZE?2Xz8WoIZySp{2&yShX}7sh@WfRIKKk4pZKvm`=#%>MRxI^|`$Q9?N=$NjpAC%H(!vjtYNSNX27c zU*Os8ZdRQ{dOT}dYs@b%2@Y^*e;95quqxJ^Iljqw}>B&4HUOW{$}be<;sK6zWRZrk)1 z{f?4+7IA2QJH~9ShjHv-vjsF41Gz_frKP)ib7wAdKt@7>KUFFFTssanp^yF`DhDoc z;cKK-G?W8|>!$UZqLx9oYVVCuOKfY12bAm8rtYW1yFbe_T!!c6k%<7PN*O4Ji3r;W z=I8BY_PCFzuh|IOy3^Sj($%~;G>QbaTULB!u*@(j7DSZXwY8~ly>#70&!6F(mQ&AJpU3- zBHr2GumCNtQLuOU$yfMZqkJ^}&M~50BhZ3Ur7O3jG`&>J(!$nOlGKFdb|sdED<5+q z32>9UXm5Uuq(NU3=hJ6%-xH0Pio7}@Jg?!rsjwz8X;px!MwIEz=cV1^XHY^{uVBV( z6QU_qbyt^mN7UVsL%umk0ia=|M5;ScV;4=`gXYs2QLIv2!FLKIqplZAZtWy5;se23 z$1WO_4Y_!>Bs|gj0|^1%k;7uCWZ02@?#^`D`!dlPnqHMXoUOv3M$_6NX*sMWhf{?X zEt|^W>#>n5`?$E293~X^!>k$;8&_P(tX@&9&|Ofry`Gza<%Xwe*fC5u1tRS z(5yUiR3m0L_Ad?BMGiYs%0~zBv2CQ(Cj@0ex-1{nuSWxZ><2?0#0Ok?kw=pPch&&t z#r1@MXAp7Wc3!D)+>`E<#AS9Nqq2e9%7Z>~U1(Ph18#iK2>2E`eri zJ^jh=PM)K#l_`oj2~FOedvm$S_+nR?!uosz$ERb3JPJ=9XhZ$$MvNX^qmDIK@lCqK4XS|)7-($Nn&d{N^slvR>)pIjbJSSg?ebBeq zqAR7>&N^lbRU~6DX=7it`D5(kKIPT1ap;-(I@4)t?A8#!HCYgqdr-1Nr3(XLQTTTd zKJALG6Y37wV#(421G=Jl7bTK}$p)v3(bKuPS@GxbbswNGF{j!#`udYd$Fc!VHMq5B zku!6mUi4h#2_$(Pz=YrDtt>x9Te-?D(Bt#VOw&%ZJ8&*%P3ZMvUZx%1W5sa^b@YTN z23p@Ru(r)+a9%bghRe2nXfNuQjOO`p(cS?Z_!V{ zBQT}o&2O6X+S#eaV$nl-)agk=0g9iX$?(4YG5KYln&Wt_rxU4G$tUB7SR7t2!r}~e z042@x~JX|xR1PzW0#)@1p!5*6&QYUePt<$IGr|lhAP*@{3wXcd_l8|4QpD()V zDFcd^u(^ao=eE{U^so55GMX`xQ+be9+#_{h))Xvyv zm;S~Po(;l2+S5^M)CtZD;N^Lwo^KNOU&5T#gqYcj3D*?CIbJHl!eg64_-NkBViw&N zDKwq{R$XR(4)iFd_`@}uK&=%Xm9np48^;C>55*ly&+RWml4=S}1J45^OkI5&sZ_5FEGo=sk_;qJm%Y;WSxqqw6a_q3^8pP9D$iU-K| zdgzv&t1r`T{891_1RZ39)S;%Air#t3y!?;bt;&g5Q^deJTB6LF;_K4Y#BWY}d42Lb zb$Ta17|_9kiNM3As&Uza@A25zQ$bW1L?l&}ic6vrsUtS)KzY``ykHtxni8^$bJ~%~ z3h_+tYlKs!)QkMgq-t%QfNG2`#`E+Zx1fB-L%$9>wdrd0{Nb;4rP2ywDm*o@ZCyT{Gm4xfC}?-!Pbm z0bR7a6N!;0*s4J1r{jK)^A4EqD?M7ru#j_pLe!AoAZ%|D84X#ihjq^5lR#3xd=x1XQd+wVbJa)?mmNQ|O3^cu!uE&Vt$I=klCgB& zk3&gJB%NeL5gRiumtnh^kEY-mJhlf=bDgt1HnW;7=AMFFM|MsLb4W>SsH4cN0SWJq z^H1Bc?TNxM(zwC5U%q}c-)2Kusj)kaxc}BNgrncSET`xCk>yEb0s-7CmvkcBxLm- zb`v`zb>H0bS@SEcM~`!pKIlWSiarYw6KC`21#f$o4Ck0>F5FA@&c-0FjlE%b^4NHA zs-pF5Klz__uAk33AvklOl)903j$Tu~ITXVk)!$2-j#HMUvuKd21>b3^Wknbqb!uOW zS=Ky+=%iVuc>@W-K=!t1*1h5uq%u?0j1zFbtj8U*os`&=+97sYhqCimd29I#OX*K2o};hoEh73c+rx+jzo`nz@RRsk<_vkMNp5MVY zx6_akOSybawtA#4oDq?lqv#Z&O@UWpy*lWrhJjS)#}&_fuLDsosA+e;qJCU(NaB`d zJ#E1-j8a|&!`b7}At;LywEKbSDjyzEhFq<%`4JZr=7jYZqvnfKmI1wxZi1(lg#SQ& z-nJvx9S@z2O&q-1}BNiEgCQbSK=0GBJu#EMpPB-)Dufvhc}vUno2@amz1x2s=zz z!uv&hDWAKjB-Gzj+Cr2X4rEFV9}(M8NgzL2mg4M8_m+TI$)Jp#+UD9E@!8QjWh;61 zfntlQ&m<@SmX^Z0m&~=+gKj_)LQe=nGfoNHWD|M0*Is9-Lrjle%J#J$B(Gak=`t_l z!1YMP@Z=GELI|!edL0LS8wta4IQ*G?Zh+ML5rQ?3P~-k)00;tX1{C%U)|uj`g=jkB z?!0R8Hj}l)V54(<)@P`?Q`%W^1;(b!h@w{w<|&`1nKW4Oicfv4m08z7Yz9wd_pGyJ z?BzAQ?*P5YSmI4~IFTHZ{=~F~TL$YO;hj+q4fo+Ht^DH={echA-V}pjV``>aiLAfu zQwv(~Dm}lEoEHvYC867`w>}-vsA1-?P=A%a?95ax8)roKY_ z4LjEbHVY?yQyCw6V^;y?MUGZhT5r$}t&ivrzZGnb@=*NYKx73#+_8M^bw)YKpO{U; zw=wUUn_P_EKYuFJ*s_jnd!AZ#w_Wlti_TH|og~@5>{BGivAsO(PMe4PCc182ElPtd zDti9(HqJb~{au>&8JSq8Rvkjr1aF#YZFh;lFF`~Uf9hJzpc%yS%xe1+-FjoaP(5tK_qmQrKtPb?8UIM zUob5nHw`S#4K^X>N=g?H^N@Y%&8yS?Lg{HUeJ-Clpvw(u^a+@iFaAA8QBeyg(WJbp z72~0d1A)9r?;e6@&pihlK)R53zm~zHM7oJRiOX7qUhg}>^n%i#p1;2iEfWQ2P(tex zKd6=ZP3?sKg_?<(<4iEuZ|PEnIw4zsn7r6@215IKuM8%KY}Y-vu?HETD2EO{`N@d) z70E(k&?s>NeY%_vp#ITsV7(h?%i=+7@jTc|j5(*lSeveWDXKBiehCUV*4U#|yn@=G zV3SOI&WO_(tBH-@w)K3Bk<@M3m)ZuUlzRY02<}(A>zUi_XJe*uG543>%I4u#a2m|w zS*09iY}NTMMtuuXkGh>%2=k(d?&or@_M^&HB9@+UBLcD}6G?zZg?$TeVWAk{cblgy z-8)VVvlMmFN?AKcK|jBT)T)}r5~(WV^>$<5d8Th?c5-lr&(s|HVfEjyhXF{SD@d=2 zmFOp5z)NY!-!=A5NsXdg^Lpi^(N+0d#3+U4lZPO^%an1SP#tgCHh9C~*vYbn^8>5- z?jcOHQU{Pg!^ z^c{A{sium|QX`!lGLtW6rJTcKbo0HhAJgg2qaStTDED&a;*+~gl78ngi^}nOU5fe; zr$Lf@+wV&_L-~KQCpWmQg`4k4wp#cbZ4(JF2n9u%z5v#+o{|K!x{_mj`=6~I# z$;kNk(2ANV%Wc(v&p7W1jsKgF7V04M*3oBTCT@&`@w&smZ`Q)T~# zC1LmnmW1&?HJgmg1kCKL1b>|W~Uo z+aHr0EUf?T-((0e4UO- z+tv(<0$Pj&50=n?Ui=8kX-yqO5NRS*hTn#OqLeeBf+Cj53*gi`1LBlFEd5Dp16hWn6d0+%{S4=*Pyov@b|FFhV1_i3%03v;CIHV)BZ2gV zc?3!U632BB+f_!80rf@S7;1mmBj93-KE%Y(cMwB@sHIgyj zELjOIjzRH81bK~-2nziYRuo9!fZj9Uk-Q}#jtin>g*7p@9Y}b=k_w8+V+J*ICOZb0 zCK6QELMAB4B3GQ>)Jt%_v(Lby$FrEVO3knn@nb1%b&wIalC8sNqMPdz0t=Y~F)6=Y z9CrAngFzw@Y{!H3%Sa39xpc1?Awt2OagPiaSi+aUGDHMqd=IN&q{)k8JsgE`8w!1= z98pq6K}N%)NHbF{l71(Oci27Q0mwAansl zau`^>0=y3cjQO?=c}P{M9u1U4RDd`@Y`Q^2W{##6#9^)kfOYCdY$OUGGOh&XE%C|% z*cBKl$HaklNPJ|h2e3o{X%rSPu6g^*G&G2<7PZ|ADDellIiM(SfDD=JE4d@0Xf0Ep zfj@yLf=S-F23T95A;EB59xL7SN^{nM7(gN7Ue^;F*0YqhrpG}xa0Q?@J-&~=(PMSR zhg;`iBd$RtK?@7?1XRZ)X+NkHq|0n^uHps(Mqn4Rh+BY48^fpAA&b>ZeIv zkMmx)%@#eD!ey_6=mVOc{jpU&6zeSwlZtvXF7|6I3#GmWM;&G3+!1`k^WCoUTpQK4 zM`FJ0D{F%PhqZSM7N%*G1dnaowr$(C{T$o2ZQHiZ=h(Jw@B7`E-Mw?MF%z-f5f$B$ z-BtZBvm+`qS9*6F4|^=VmB(s!`FvD*YVW4Kzji_{3kDFq|9Pp}tfkFm3xLfzsZAzl zX^STM>iLhw`K8t$ah^P+TvdGQ?#tx;Y&!QhY3B+D2Iggl>t%gp+IMxP8cOVSfBhhW2?#cGh*EC z#E+O*b2o??ZCzd;F?$bApQ&=9n-um{H$}m#yLXU@Wph)-NrvZsrM5NIc;{YKDK>#~ z>#94`m)PWQS7>cE-F+UTt!Mo`>rFBh9{c=8*CyvnclD}0yyhGrRSU)FDEUYl!|d4o zoqr?UG4Cp1BdiDJEh_Hmo}ohc1k8Nxs2Yo*t-8)Np_N@ln}y2=?>-#*)ZgPL?AM*c z7+Th2y^O{7=$^k>medny~#xX~OXDl?m&=6DCamQJAQRtH{bL{-YF>HUEp< zw2c2L%KG0|l>bj*@{c_D-wyfy56k^GA>SOV|NVYiCQbrcPPTt#eE;(;?Ch-nwKDl* zY3t(jZ>9D&|B#oxhodvSk&BIusq?>A5dX%N|Eq#v`o9$f`@f6Q{*Nak1H->D`ak3U z%eyT91@AI3FfjhR)N2+NPWJzXdRbXHnf`aFw@pm^K2MSzBS1<@P z-9QjH^vw+&VS86s7v4|HtKP)M>HSXGrmbR))-$8&lbuWj7-&QzR!}(SI0^-%qrItt zp~*gIIAwVw1F!~0MuzAxSOU~@yjbnUDTAen&F6}UT@Uy2D14SxWgUsN_Xr>{IRxBRB5E)@R{ z{Y(~rH%X`Xpd9pm91FnNVhGP!FmJbaKjBM1dAf5m^D+yg-`S^Ml#5?0wuZLW$B$b$ z0xxlP^?YUlKodA;*SB5W7XRPlQUI1V*QVdy8m3w@*A+7&xKvjGfJeWOYF&~V-hh+I zm0B}30BB@x^u4|V0r1CP+IzhYKS~BmtMaq6$;I#0%%3XR_2G>H)$OVK-KL+#cm3&y zu-&Rdn`_89V_$muDX+2DzTbDVyFN!rj`V=(8eAH{YMg8UWOH+5`nT8ZM>!k-d^G=- zAkH~tfG2NsGb3k!j$U}c?$u#<13<^nUvt6T)$EA_{f1wm6}RS}Ae&o@S3479a0bqf z0G)u7QrF*>`d{1q_uJH8m?mc6bR6020615HsJ=p)U)*o~oLzHv;PuU{uLyg9^y+S$ z8h8ZZm$l{FUwPRcE=V+ zu%G3_JR$$B>|c-{%8-^%ecl}x-5vDv-7mUJAm`tyXCJ|I|KIy?oZCvc6~8F^-^Xd! z{64VzFXot@XFoB{UC;nITQa|uz(?MkaePmC(vPs6#qjTfSDXXCGaugwKjc*}LXzJ( zFSH8&Cq1BZ{->WWCcm@qebe8$uBa`1Pq&0$;afT=zq4)8d-$F%itnuUUESn=fs_A$ zir@c$R{sLO{{bz&3f$0V_@8bHpTl-^oB#FD-@b@b-mZ$Khz#1fXa3fk&*#ru=vVB99%X%%6hSY%@PN>_;!a>EA)Wl`r})bMc>$TS(g9!B--U?~q&7 zw@VD>zO;c8dT+PJZ|L2UtDiwP>QDYRUk66cuaH}{{Jy*G$$NV5HpdU>-J0xwW{Dlw zf3rRQK=0M=_-6vO8^8UolrjC+rLL6Ie*w?`03N^4zqe7EDkw+iL;WAVN4xy#zZG2Y z{$WXDxBOmK92(pmfTqK{bx>wzwXe(HG4&3lEZunm!{Im&+^^iK}^uc1PZvn|xCTJWV87~YeN=rVb3wUAN~gPTIZj9WqT?fB?06uHBAl)mBN#wmnLkR^{v@J9$ptM3{vl@LBCf)3e0-liz4ypp zpr{1bxLp+%Sm2entgG4)=vgm&8Cp`!P2EbDkj5bvf1u!esYkpLp!>>#d0V5 zxhswp+THQq3SNW}`GV5ft7%if|080V`<)_#sNnheo&wL*z zGPoE@@R4p2%)tnKl`4!*NG(NREZo&~+q$$+nvm8Cr3Uxu{@8;?nR6G-w_bIr+V*0G zY3g|G%C{wt#8xsk(?b7 z7p!Ls$1_P;roeZ-38^9UgRF4rxecpYX#^MVm<_(8VH*;fIGECm><$=1S=3m13O12B z^_8f8S~{iMmL{XUAPSZfllI{qm$bjs?wnJ;<^A?uIMHToz#>WJ$wCMOkKM9^c;+Uc zmfwU@8FC&3Ne_E1)YJAncNm7OhKoWCMiqJH{3NII<&?*Rl8_5y?J-D#(P{s+-qz=gE@!Ce~rCD ziJ)R+Z1i|0x^=-_*~3SXdMNxi0p*EuCJ}twPr8iX;_1^Ds>4;@jc`bb8RmX*91;Ji z;&|1RUX{K(QVsy2`NGsZ+?-ixZGy;%J+T94QHD;f{Q~ z@t-L9;qgn+Vv~)qoVMuJxG&Abg3uP>3X*e&uJj!yP_@a-RD^Krs|Yn`y_~jme)$@- zty$j~fx=Is4uzvcgo!VshLiDHmt1%E%Q#32JC{!wL-iy8+eC#cN(MaBo8Oi?&3jIi zZkJ)P-=I3Bgbp4SP+zjmO-0orn_K4;76Jao`oTLwf2ynMM!>}qn34Jy&8v+A;k^6} z*@5BKU=1{e3H9UpTx4#tS>p)9Z|{UBQkFc)Ryp2#r_ zhF8#Jc2b5-dP@-_>N(Na$-lRvSV#N44$@YL`bS{cU7ExNkATXopaZA z?)$tpH)i)XqLMBy()auNsm>n za7G60NxUnj-yz@c{WuL_0&rf3vpI#XP;`wD<%~(!EsXLn<-MIT;=CJD82s_922)JV zhV#N)qY$uE(I7%9DkIior``B`L*y(lf78%`+;%2}fI)UqqR@pO-dhbPIDG%Zi(0(rZfp&^vI}7P)(aphFo#?JuO|+5V z_q%<0zBf5D4Q|&2#1=8oM;MSX-`#?s2O7xmaOryH}(T@&?b4T!e5o@Ep32 zwWG4OdpYkaw{R)h{zHEA{X8}Jlek9Go+7)yA^j-S1=n><=kTcVdQUB8vnZNX!?jN% zyrd;$ii<~0gU%xonedWJLp?a=sTZZi%zgMkrfI`OU%UfpBUcQ_2OYXlgXN^|)w~h!^(Y2aFX}24y#0LdIn9`ppa>O-QzFE`;$T^cjh?-7a&Xl;!u9TOKikXU<5rPcKA>yA$@WMu31r|mWo{S@t#E?7RCbk zN2mQ3cj{>q_{@YCWungu?- zUV$GY{ec5$^zle@39w;McHu)i?yU4t)a=u!z&oyU0)A1f?;bIk?(pk!r95 zH;*=uE8KY-kKsa000w+rxo`FrRNS(WeJAkHlmpW9id^AYoEhH+bLZ9<^Nds;w3G17 zK)KXGvr%6^_q_>ds&+=Ua3mojB1F)3``MsGH=-kOYk!p$)tABjL+o^Jum)_ z6oKE_oZd(u$-~oFJ4@(=V|KLP9Q8XyLB{LN*&AZ_Se|bw4`0u z65B_96zoM(m@SKKl|IWk-avFr3nI6eY1+JgO$>_bmuSsf9+!&aj~t)oz3nF^HC1301eMhb(A}i;kM|frG!Hp=MT!a!ue{-`%r|OwPW&B-k1$H_D_< z*_d(J!%cRS9#W2wfoMAC^QE%K^`YdqG^~bSHrxf=aVB?YeOZNo6}R3W8SZ%SIppsr zM^%T=J|V9HU=)_`$fdtaC;8Zg9EkjFz6Y zSUiaW7_^7))eB!p&1x3S2s8C8anzKHV6c%fbR^r0Am4z|;|oRn9$b^__KXu<{SD2f z&&HYdTHkicngsy$DPI-X=PJH?D^tY11mSohpmVP`q4jFc&IO zqTN1@lq_CFYjpy~W`F-Y$F|6Ng zDV@i|SsWinXee#L*lD$R2@P~q8;!oEpW?=zP#27o7NcCM3Ca}#L;t3rj&dY{cB=n` zC43xJBOq2Bc^dr!j|w>3Bb~U-h9^|v%;+pcE@KcUD>tsOw54$=sq=SQbkZ@@;V096 z$%tt=mM4c>lh)!ncaQ?=%hI_yh!r-%Oq7M?iyVreFgXtoX;oaWcZD);|N8K7j9c)3 zgmh@Zsfc5R2BBn;m6LQ1I1GMzt{z=p4G(hbO|Ay9YH1kiuwX$GgC)-a0Y^Db6QSwS zRAR-{!n(SyHl2CzqB>o5*5{0L%gzrrnX~>}xuq&2 zO`wU#{eZ+_3Mxk3!b|TSWT!SZ7&nCD`P^b_RSOX3nC{;*!K2NTMiFo$sWa>K&r zo(cwwyJT>V?NcMaZ`K#1v+696$2IBfL#sVX$oK17kA4gRpZ0c+wQhERTe;znC}^D7 z)XVql_6XEWqnwKQD4;3R6h|t2@rp`&B9q0O8mtr!Sz&C`&E%ZUr$=6WT`Wj(HI#fd zsO8l=jXwi1+-jehGDIB7baeW&*vD8=GKWbjRF$t1#3Ru z!9@$(o6aoHAz4l;8(43zw_@NKXKMMX4LdLuSxPPyGa{N`pb?A*sz}1{Zt{hh-7CGb zmCG!i_R#zesxB(1R>T1gPjKz-pgj$G>BhIOEJ;+xH`x=~iLtSHcy=d~d(&Q*06blb z{z)zGN0gU@OIj5DQ;x063y{12p5~%iQ({ZJ9(fwbpJ}&^e1tL`o1x^#33_y1w)vD8 zmOBXLwr?#SYhtq%K4^-Rj$RpnR&2M`j24ulhM@&*n__8IAl`||jla-f2WeQTDh({( zzkFJ#MblL6CEu%qJ4|EylN$Ruuq0$Uc8Dn8u$$|^b&YyMLN|kmr{wawPv>cgG8VoN z)#9J+^#WwH72gPk+d*$}@&`L0l**z2yR8DZpQo;=@D0lzHDT1qe3c0n_FG4!U(2*A z>wD@1c*^aL{cH^O@LnI2)JWN*FM!p^O^v!hp%ac`KW|Z@cZ^g-=%+j!vAX%OEFYF~ zScfai&;pcSLgyw79!XW_fl)@LGp)Bq0MT=qsiI+JL2|4zgx$csXc=p8cy;GK*yq`e znT+zbl|Aml4Q@D^Pc+U&&Sm-T`c}{KTFoW%WPECu)F&rJ1E^fhXY%a41V*+?pD5}y zIK^7@Xp+32>t^AzFyTdKYvpe|^s{A58~jeaBg<8VuoJ(?U6A7o*Zb4Z#G96<_E2I< z`a`mdI&hb%FNJ$WH+1amC=IbJUFMld;(S=1xJ;2xv3jF}I=wYZpWJ#K*kkV73{brv z*A{K)iVhZ9gLsw-rD$->egN%==^_2#w!a0uA`!XYMU#(`*tOw{Ogg4&t0LX9xJ{Xo z+#6~4l2&hXFGQffuyM&fjA&kaM)LPDyZ$roJA&x!LXgK_WGftP7TPq#!;M)6b+8!V zf#*Gz%*dMc8VR7=d@qHfFH?K!3?IXnty?b(ZmZT$7gdiB^+IlYzprVs zu#zPuo-XNccf-rMHMnwwb>>ePJp5PrL*X)rG1vh7#>}*ek+3em;~GC+Az4nEhT+t&7fcB;}YSN zlzy0)F+n5-X#&xZ;z6f-;s>4(8F5AqM|HqtWMD08IS8UcaRdz5Is?i#Dqn437 z?c~&^DDP!oZMK|k>xxJ;WyEdMdkcJ<4PCE0WIbcTx`s5a1xuRbc+Rd-n*jwEB=37= zAp0yt(kEc@=zA{s6PpiqWPjXN4o_Zo-qvhM)pOB(Z4wXTh=E&?C!GFrEds+<_#H?h58+#4? zhFZao-|N4uzJ@4f4K>V_a^hnpAV(_lV52%;dAf9|d%tRrxxc}#7_$W}dFgx17S`=l z(o)C2_4lqm<~KT}UARMq`Dl4p+F5~fZcq;6O=14 zY#}a2U1b*8=}}5I8R+)EXHOLpRTV%Lh4%9)3`rJ8_MeOsm~~0!b)3SfX(bn%E3|j}*P5WEF{NZPzs)P_X$b0xDBNB;;-LWEPpx8w2s7fFId6U*QO^O_q$3(043tite3f9j0oMxh}gTk+Gi!IkMcQx_f#I_oCt0epQM@T5`I6+Si z28^l6K8e=i`-Knf)51=I8 z5c+EacOQ;X7w!_-jceg#CGr8~GbTu_P4NPS*=Vy?E1G?Vt!}XJEc3y*)E!uFFm?Kq zhF^P|7=4Rt)gXj&VsrFgxSQUNsJHjyq#_vx@;7BFe5+d~~n zHmcRc(J(3#Y_leM@4>+iG-Q$ZnKcu?nk%8{8^Z)(;f$%}6qol1J5|%pl7!X^`-$c3 z5aJXI$6$3w#YlnudP_x??m&@A{pn%lInT+K1rL{(qm`WdDX&$sP(Q`W)xuXedvD}5w6R6Wz70EFKBv+x=mp;=Aymc;UG-IEQD0=nVu7(3G3Ht3VfoHu15Q)mN!Z6Wl8bC*pCL& zcYp4b(MuoclMoU_MOLFDFkOc}aOX#fVAXp*CR6qwgU;wCng$}|sjmS(aHcQGI1v)`C;g* zRY$qJHX4->hYRXlKX*&70eG%oXXG)=kiFyi4$h)u^cI?mam>IJMZfr^kkKvLw^zq-}6y=l~ zN^Rfwi{Bf7in7exJ}@9U>QSu9HMKcV{-TjZq=M6$9lpir#Ksz&jsAn-{If86rhYy1r!``f&spf4->Su0+%iv> zd~W>!bRefTv1AaK#KS`edN?_n=thbCQU`jbgJl~Lge`}_w&Enq`Hj=*opvhTg1>yb z*|>2}5;PeFv;`x{3zR(ag;LN15hD;=-tqlQXM`q)Y2h&BBE4|MV71y0H&IKct{%2s zEtbmpfCtF;>wx$r`}(0IaY27Maqg`)`y0y)lx+%c*<;&6{m6x@)5DM=N4cF-X&D;? zC2iASZ}i#%Rtm7g!=XO+KyD(ZHiyY)hhRBFYOn z;AX`s{ck?bdL`RO5O%3R)}IXvSnZECmco^*vq~0xL_+)dEGPaxpVNy|nqHh&6v<`( z`!r(+=7TtMbPRztJ)=Z!Ke4Nt0tg6m74sHVm>_7FI*DvcB)k;{7{Wi)`@{wY^rVDz z`+APdHS{m6(peceXW+V1pD+|z!7D6Ue5wY3+h&h$*+qWW9CTtB5$iGoODa(XvXbna z>8YF`X8?)T26G$nqDehgYFMrLegY{o5Vv{XB4~U0GDG?>2@5T zEs+lWo6Quo3drXskU!DDoL6%tSYum?!=1)2*yT%59D6LDHmJ9z5EPk$G`q4>>C8mR z>ZmC;8zv>&!Wk z^`7mEiluzyx0@PXRUyaT&Ju!F(#E;;UEllE2vp2$+P$pVDr4&LrH)797|*SW4dHT? zI^Dbp1zP((#Oxq|{2G&s&(1>_QUx(0WAADM-}1;1DkFfIncAj$Q)H%)eaygkc^2`p z#83E|FtdwS^-(ND-P|Z}%q5rAu=+LYHT2$F!NgpsL|{Ecl3I&14*r%JbAs!{He@f^ zRd()MLNE}L|9u!*<~Sq8q*vUo4%`!;B7j~oqDB+J`Lv2F-}Ah2S_OqeBSjkkME>n1 zaaX2t@CDT0tk^sQ4%YXl;s^uhu?a%VOq(_rjh2q8%Nt+vi$>ZJPU^*kO#{X7lq|Es z3&)Tqd?(KxDH+&4jj^X5yOH#xC~v5X;D5J~%ns%)p-{DSY+fy6I;#29oxFO10Uyr7 zb<(PyLPz}J$(vP2?Kn!;XjLP0Gv>^5$ki6F*Gw3zzNtx&yUu3TbdRvq(z_tbPMcuH z5o}ONjy1Xxc>jJj&QUPvdcZY__%g??h$gD;jv+iggQpsqjHQ_}5SJBz?$Tt?Riv@?1P zX+c@63A$Vn-Pf*9KUU_VDTDVCYb0?KNsJC1-e)`I z;`AO>69AL|KC+bAVdGTUiHCM8f{=Yfxwle>f5DJ8JA9E=oZD!MItj+luweU*XT;vZl&CD3JGPIh%Ws3oEaFnH8k_4Ur_sA;C8wogQ=yY}_lg*#}3Dm^t z58FA9!3HD*%W`l)FiK(*`)l|M>JwDgRo1u-)Z zPac+J#2@enQ2sE6xaG^=YC8{eu|;Bc7ArGJQ6(pQ2x^*-0~vkb-dS;;XoJa?n|=}& zIUi=_#H3We7ffthPO=VtX2>LZ zlPsCfRm%0Jc}C`-lyK;yNUXeFL(mlx3+_tWNI0I06|Q2Gwx94m6(?x3=2~GnoXJ_D_~eV6G|Qa781Wm3mZgipgJ6jN$yFBb_|?ABl$MLQ ztnNRBnrysg-!Fp?acY0yp){a)t1}{LQS3o5q8(nQczd>sTNmFj(`z=Bkodwi#P`$c zL>nJD%Q0dmjYENFQ{=bN4_cxYIrGa@fzFO zAZ$d~-Je?=I`puTf#{-a0Az!hmPSWyq04syskz8W=!wJ#@~Z$y4CoIEUjm-}aJoc0 z?9-`!Ce1!dmvxWj%_B&~?(40LONTUsZzVilHl}~pJ7wK=NHSv>4#37GN9=MD|Au(PA2dkpv(?o++^-yhbFF|#MvvJk@|{g>({nx(UMN9zqa zhR6Bxhr;HrA3)!0tiNHS{Qx5qp&>W}W^y*C`o@5f%NCh-W@q}2+8--%A%n$35{ z=F<~t$+t{)1m)6lOl=fc{ts@qxS>Z|4DIJ-8D?a`Qp4r3Dh!;taH6$Z?drSumBnpk z1w<@5-=fEbl$D!-)jRZf=Ecg+!f0!{b}uJ)6(Kg~5{ghgj7Dkv8%5o%*vK!*WpVrw zMVJS}MA)=Gh>`;Mt)RZH431UXD7CXm(Yek6QoLnY5^V8P_j`3#+`!0K$cmYPE5tLz zkBtQH%`y(L2Oa>W0f72*Pm0%n%!Q5@cPd*0amjHCRv$`b(~)(lR6WGpq3X(O-Pnub z>`9$Po9v=lBNFUaQ-IBY>e4D}sEV$l(r{k0xeCvXlNz~F&~K^er(&N?Ft$?rG^CoB z7vvYY!z?MfUQA2qos^k38%AK5zNLOP@8p;aOa0(i2+(OJ6tEh=TlA4e!QO`>XD!mu6FBi&DqG` zthich`-f&6rnSq9@1F%X9D~ooX75Xg!D9sfW}lztdxKObYc_Ag1*$}>bN`YaR`SkR zoK*v$8)aN(Up)^K-k9}>&CN8_2x%Mf!A35R3K{KM)a086ut|Jv90_i-oQcS zT?MeLPd#-Hu#vKTzSVzNBL#RS*DLc`zzC|yQ++K4RqIKvS}u1))JbH%(sdmDmOC@; zoy+D`Cw~Mnd6@RmQUWA;4WFK4F-5N_e0K>YYVjsZraa3U7CsMjt>?dZ^*M57@jDjZ zAsUaD%26D3{OgBWOT#STv6Op)CIERP*sR0iT(QR!f}&ys76{0Va}0wmtuHa{F+mB| z<#G@YH+8HD#>M50q~Es<*s?&II*?Q&M8RCvoPc}lt~V-6dw?_QmlcDBJUEs*&33hf ze9#KXWbT|;r^-rhu`Ra}UG9Keiu{zwZw6{=_X=sM2LVO3l z;GFTJ$Hne`1cv2-0;*;4mxZ0o=P!n-7cIE-X-JXk{Lut)_f*^8K`{1;tMk}kF?QT1 zt$D#H`lD~9$E-CL{M7uZoBpO!yZmzEyLg46hEbb=OhMY0#NUc8^BEC?5UJ*p$&DyJ zf-!qJa}AxP2vV8)oycx7g_nT(n@dxBVUZBs_c8bt$e_Anz+e~lg=HgghN&-W2)Qb2 zqK(R#J_h^3t*MaO0#x9~mMv$XO~f6vqg}MXa1wRH?xh+jYYeNb^j$OVYS$>wQZwP4Djx{F_fk#`J z?t4pI4>&aU=tUPFtBQVvj^J8u@K4~09nkggg=gxZ4a%t{bFT>?>mt&hFbuF+tohma ze}7!H*Vg9HG2Ufhl6SO>G+aY;0s@rUYt!JvpK9^GrzKJwY4GbgPbU!CpoO=UZU=?K z|0=RPa(@H`D%*S`E#8Om(LZ5-h8Sv3eC?5LkbSZ0Yn@P{RbVqm`Xn%QC4wd&ydliz z1S;gSI=;I}t8K8dLdXo6nGj=(?oV-%an;s{@SD@x>5wB^QP0OluH0yl=jO>?ZAJT- z9t_dYTS6rb3+{S)e_TZxHyp&?hXr9|)vQc_PnnW%r-A%I710z9XWtO5^9r-YKR{o4DUjF-Tn4jd7|%K9N{_+ZG&{8ss;g`T10CeatM^@Cag*H? zj8HFjM=shVDcE0$mdVp$4e*jim29|E$BD32l)o9V%D$0W?$@=C7SVF9&2@T!}a%#0@~Ao9r^s2Ku88mCL z*sUTIs~CNkySz`=1v@hYY**8FLZZZ(R6@(?K}E{H$&060N67Hy|YAT8^@el9}R+)U}8dQwE7YUIQh*@!gIdeBycDDn6gckjTx&0re0Q|#da zQIzr;68s0mEJ7gJ8h_ed2JpLC)r66Xz6%PFxsEHl=2-X-)0IeodI}{zDp%_2I8!%s z4{&pd%2#e<0R^>=I8I15_Y?UZ*!&b}Ql#d#>qj1#@a^()PDbzucibg2L*PAeC}MrO zlc8(QuV}@luXnELBS4$}Oi`*e+vMpEEptpTdd%mf`ey2@vZ9dE@JjL>d6#guz45bSjt z(|^FlIqY!(Uzmk)jpN-EM{X2*<*E0T)+y_f#i#s@Kg?L>)T+63iDWn1< z)ksYfm2}vt9n@Sm7W7d>=<(vyThoTs#($pEKn!ELbj&3Qfw&4eqI)Y6O2Fi&32=|= z-OBuCxP)l7YT7fuPJ_-DoSQ?`Xi1Q!YL?>^lCC7oa*{=G&$Eq{5zHkID3I@g_hCIY z(K%(ZHgib$A<1F%2k$I2jvL&7})p`8mM1A&N263+DmjTgIGUr{JB zwOgDt0n>K6jV#FV_)PFZ$#aqdF%T%NSHE2C&qef_itszBQY0Q!dkmiR#oJgu;HHqu z3tJeDsuF;oEU;!WnbdGdD7+)y-rt5i4hk@VPCWNF@WGkC!at)BMLU) zz4C99NYQoo?BVwns}|5KP+iVF{z>QZ!-oUa|ofRY$jf62vm+DMeZ(k5?(b39qHgmhpqbRu{Y8V;2Okx)(lv zQL~4b<1s`mZ&DB+0ps(t^ec_P`vRiPQ5bTwr{L<98LFS|D?g^b*dk&#Acs_)B;L2K z?_B_;<1$ToObI9NdJ7(xnv*B$#Ot8~uHgohXza&WCfD|1OFYya1YGy_*Vik~D*v5M zy|YWikp#VB#%*|VCC{vS1$OdHzsq*7bRu2BfZg^WZ&7tPNUjRU ze_01EY+{0*Un5H8Jelndzo zxTU(f5Y_C+yDOvn@H(_s=-H!GtRv95O};YnyirP@R*yQByp!qd+1t_Xy<4tI_pxJ6 zF^F^#w8{)u_hzr_J#JiV#uw-kOUI<1Vc|P(bMzy$$|z+GrlD`K&9!ujIg`qS7Vh)p z>V8>pWl#@cYB8RhI8F!66_0nugkIR2nXh0d>LTywM!GLLmk444b4N$xFxrp^X+&V? zYF$p@y))UR6F_=sun`lJ?9kh%*-d`Z`4=#9rl(h`6in|}b>O%bj>ge!T6;-^kZ2x~ zyU@}cQtH++&5ad8+0r?G0Z>ZYg5u@J^onV@WE(lkc7*16xVvL!VIR<0gE9%RWJG@T zx*?pwY2aK+bcm?yLz5i)GFps|pi@z^os1^Qpv!MHdpuydrj4VOltpw}SFJ%})A0My zL}AInlG;tf`o`Tp6A7IJsDfvAe^6)ALjooE^{1m`+DM=?;+yM={3^G58>SW~P(r$4 z+uGij_q&yV|BaIgmBQSE%H--$bN@%eEU_Hr0!7M2V}hEIgdHM42o2zLkkx_0iBO(K zRvkw~;96H>_=NC%wv6)a1PpM#?2c4oVx(Se8nLy-erpsIwjNY|TpS1}ZqG_*+vl~P z3#Ir>l@2nxfU0e0?lv1sc!i^pdC;ce5?c~%E_lNNiqqI27j!Q=%*3J_^F5yhyfS>} z)Rx+?{J=f0Sz8A~Hqf!t!t>Mv{f(#mqO-HBk_Fn7DVRWpH-(W8N$I-u8v|?2uGJ+w zbAR_Q3BS*Y+>|HGJ6Q=u70%z-Mt38;u1+myOqo1Ni7+&T6WwwDHUcrR>6(1<(a}BA z0Qs2X;#m%v7YOEtRQqbtxUHEf+V~*(0^15*`oudVt3vEOkcsbi&PgkR*XavXA^$H# z$h?l;Gf-?Y!;}i%$n?T&d5dGuk1ZTzWJQUp=5(Pf&06fz(f}Dl>UrVMVe-MB&DUwu z(zT8@It_vDzaljUH4jnvr2*rge#Blzd~^J7H63Y&$|6#>V?^m&Zz8SVdy=`2beX|h z=yFurN+aIEFDb9$XOd641L0&~d>X|0#|+_@L7!fMl*zmG7k5#yMN-b5OQCQU^N3e< z*%pU41@JR&oU5Od441pM9Rn^ z^`+((SMO4(!YPaptA4o+KbF^_iFGE8afaWkFyPGzYYnwSf8oJM12p54d7nF-4L&DT4CCSl`4v0f=Lv~RKjb5yS zcmVh=uzlRe{Ev+ii3q5GU-@ytflE~taig@*Ax_n9!35pJyX}DTbkeP13zc9Td5C2>ZWS7vG>{33x~MK0#@oNS(yk1dul4ggvDsyZj^r^v4CjKHS4 z9s-|lJ3@-Y8R6 z`<5a1g}ddX8)<*ztMuldm&gD)%v(ZUzVSFTY)SBZs*a7;J+hj%)FBI|7RfxO&G?Bkl_^eLnBghw6Adfz&q(J8jU> zc0>!0cAQO^vdB#5l{8t*Lb!U6MMpVS`Zy3Qy<{I!`qt!J6hIcO;r(T+7GfMc=tO`& zxucNBn6^v)`3XUcs^6%(h5MMAo_mXJG&!0HGj3Z^gQ~0}wELDqAYv<<`)TClr2SB??g3i`0(%59Qj&TS%N>VNV>$hZ?LsnqdbTe(j!i5lK? z5zDrvg41$T~ z>7=<(TKH(t8}XK`kWd%TPc0!zyG^>k9uI6IU6fZ%=X>Wqm+}llh^cL)rSjeqOZ}Bs zz&a-O@W~jZ@TyZjt$K2j1bhm@bZk^Kc^j_YXNu_hWFHBV25#f8wuplp#&b2xi zicqYzp`VOiZrqbD#9Dz~56N+iPFdHu@Ec9xX>Q6NM897641FvU9y^IGo;GGFPEY+T za7svR&Yj(V?KvlTkF)Sv^e8GJ5A2`1+)d$4o9rZEXIgJfn)`W=m$5m!eK%!X|4dBY~1pULFe#4T3M4dMC97fC<(ykji<| zf3oW=r>^woYV|l_zvcbz&_DpO#lFOpN*Mj^!kIq~tG zE#r&YCJ|J#0RRMTO#@lRmw+?r)U(>x%GI!p!ZIlWf>;RBd}6OywJx(8ArqB(Y0jXd zfos4#zoc#cP#GggUL$p7r6|9y2lw=gRh_xa{Icom{2}uEV4kQoB&(AYf7oS$>ISR! zgBCl7`azSF_ihQE#$AgK=rirkE$6vziP#*~CuB9D9ye(_y6PR#wf*rB7BOM+YvgNr zQc9Zf5yfVXUv(N6!o7*7i6+lF;Ta963DNIv`$Rzn68p!OfoK8I7K&Co)f^o@SkwmE z1g>dr>IO-;{7F?~%)QMK@|GmolA&2u*2V==<+J^v`eJ-Y+t8`Z}O& zwyxj{+27W?U+|cY9p3-!i)a1+A+qORMNj`t&lK~2bjGWxDr#!UPz%c{{a42L|5Rke z{J)Xd^Z#Lt|6f=8KW>@&S60tI!@qgcISDw~IR9%~yqOujnI*lM&HvLl^*h7}Q~y=Y&wr?!`tKrt{%8Bt|3%w7Kv}k>TZ5qtXGCP!wr$(CZQHgZ!?tbPwrytE z?3?#i)vJ0{ulw~sy2l=Ce|!1c`- z5+K_Dx~6Ag#bsb+`!oF`&%p4f{oU?=n|`;a|C6oYzc>q6n0_-CvEs7O)8n!*Gyd__ zqr+upV!&l#W%{#@fte1M>5rTH-Qzc%5E~uKUwwY(|7iQ$vM~I0Z-0)#^w*elwDhe1 z$k6`7Rr-HS{HIfYbo$Lz^mofZ%lwb>KX3APp8hYVSsDKJ5dT*HyPScI{*T1?=Y#os z*>5L)+u!N;nE%DQ@Xt(Mf9G9bV_^O-+64wSI{N?2y1>Z9%>2J5Jo;(InP9U%{6o(& zh_X~u&@h$gtqUOtubtAsm=>KOvR5@;D~TNTRj6Kl+!%O`jDK0LCoPW%GzZstszE2bPgXfPR&dT^RDEhzx7KyDhY zo*oqtI^V#K-5NN)`VU_+QcWPoS?PpthYAUC%7J74fq+yUAvl2hd*UF1jntp!KYhbjwc;&-?#vKr$omA(~`T93l&iGt04(oAt&c3esLL)*Z#wUJh3ArPH zn_}KP@kpZ`b+4capmCu~@e}ajZ0*L0?^=^N#SQkdzW@_C>Mx{G%j`#%X#}UG^a<~m z)&^~=a1IieS3FA0v#B1R9=&+MzI0ggz%rgLYIPo>C9~TzUhT7HUvBr9G{#w}Qs0FV*|1y-Z%X8urSyDfir`A+lxAgnW2UwKQ$WBW}+pV)#ZaY=ID+w)w zk_Rdxk>`rYFU%+Qlp!RZk-iW4)-FW15D`u?|Lt=v@=k(d~khVMgySb!>yub^Dd(h zVDCR4Z$OMy5e58Y?moFarQ1a_)|FIq#Qy1anYdPtYOXH zK%Dw{GK!3(6ISli`u2Q5Bty_W;q@`Qp*bsMTS1yRa|ajo;Fiz*VDW1;$4Iixr4t;9 zm4j@d^R+!`p))i#UeTq{dUybE6o~s{DoA%wN&V@0*(HydBJp@z5^XuPpte>R1|Dts zo2QbdS8)k`Q5o$E)o0LDLx+@QMLHI_Tg}RbsBB}LsljpH!82MV8*i-zd2jL!wragm z@u})D7;$k0O_wa*db^83G!uBA!YRY#T|iU?#Q^rml9~LJN#ibn@J3B) zc6p~uD{XG3(%WzZ)*1qdTb53J!zP>`)rIS;ShB}j1KH~6E7$ic`Q^+jCD5ok81Lqm z>jBX+A7~XM^X00}tAP_yRF;0<&MNKeld8a{Zkm+=e-V)8FsFob`s6Zw|8xOGS0HXyrN;YKQTr zMe}{aIv<3z%R8Muu^)HmGboZU{&=luwwS_;!%<-=ir&++Si4Z()qX-KP?Ry-sC#Z= zO|5ZHTo<}SHKb!#>Rpe|(y^qfb6Kzd$#0macmnqf zz|3+o6IB)(RB+CNA9GsKP7=l>;4f%8WJHJ-y0!;Ex5qc>6@84K9RtSZ#+F;hkJH2j zeU@{`F?j=gOG*Jb#Zd_@5D@6m<-|;?p`EN$4#)eF!1REPH3Zthw8CyNb^iGQfX|LZ zm06_Xuqw#L3cXQdM$v}83K`Fz*0CW)Lw(pSz;G=W94cW}Id;8#Npd?7=>;!ry*(>8 zZx#e$=<>t=;vOh)c1F*uHfS|9OP~2!e?Ke9>u#a4V$bH?H95n@nVtc-Tr`dXoLkQ( z;SQs)0eIZnGf7xzB z`Sywyd-I^?GM{j4~lNRf46k|4YvGk!x;hVa2tL27Rw&(=9 ze)Oe0m3ArkOrq5*R{kA}ix(PqtEhuFvxj#1@=l3>h^533=Q+6*#4GL?{u}k;xN_2Y z=dq5`c=Y|B0nf}L zFYBIK+i^DW2NB6An_IKpn-2JfC#GbCka$rReY?BOPH!3|Hazu;gpKaPS^O>tn^CQB zzea*C@Xr+WJ%Y)Qd;;AJ`%g~z^PZbm<=1TJ*g7OyS|HvStB0ruFV5{PsuTfx<)qZk zV0I!Vr-sAWKe5~QU}@S@1Mo*DHXP!P-!F@=!Am(;Csy4RL7|*n?;0J$6hy7A!c|sZ zr+hm{&lgp^g6?7Jt?&B=4~FANJ__m4Kp!xksYBR3jtME0DAt2`W@Ax0iiD0+w0$GQ z+G`u{88zRtl&%yM{EW69PwxZsO5Z|XIvx-w%O6FEkUS8Io%N9esJFFg9Qsh>0sP1nhw4%%o|T2s+~XY#jv%su;JCs04aM4(#Js_}HUP(JgNMZ`BQR0nkE*g8_i z!bQCMnJUseNTz8w;G%PTxlFLlMqd)0P zT*rDZZh?lz7}Ke?NxHT5b8m-rt@-W5bb7WKLgd49FPbBW2+kM=0I}~3F3e9aljrAK z6GFG#xhD^hI4rW_?mG6OZ={!D&#RT(Fo?QmjyKr$)8saPkryTdq;TFB?~|IAq{TbE`Kkb02r@aV4y5md^lDzZJaxObe-fzGg}G`Go$sv zU{|$rwjPImt#xU_9wI!`+cgIHM5gd4_<4FL-IHlPj$K3TK_^@s4dYQYj{r4#CBF+f zA^D8U#HJH-{1@HO7)cf_)ki#x^mKuwK|bn=Di4ZxSKJ$Kpo@UY-I^2v*KplIYSVj? z)?)F|^O8|33bI`1BeMoohh^x9E|E6{*pCN=Bnrp*E9&M(2-{16jPkmy*_1kD!7NYQ zAAOt>JX5SpJS#bUH8Din&Pq}_-+#zr$}?OTnpf6)huzP{Y}D#@Qggmi6Go|Vk=vxc zY)LSf7xwd&4Q0vaiWd)mb4R)~m$=%dSS0>9@Md(*u`Rxf=y}A@6g|7^B=VW;kh84L z$-5A8_Wbb$d(Qq*4y(3Kb7LO2lZ8yC)i6a*6bp*1n=eIBC_SV$&-9RcyD>o)_pXoZ zhZ4jC!$#iG=x(t9nj(e|NOGsYOkYOL<8EuA9?TbX^`n@Ihs;-4fSv=oI%xaKX+pkp z=xK@*6$V78p=5HjZH4%#c6$cHTQ)X-7jO4vA}ZXW*y5Iq?Hzj(sKBSl3?tRCT=3t4LNjVI}&kVzlYG4|RK3Fgm!kUTZ$SYaL z4(;nH@a^gtR*YJE0)vk|yKTOmfX-&rIg4kK==%ym_+m(l#Ksp)c?x7(JYE#1fkXR0 zDJNx&hg%ICsq@+&Xs%JTPIp_}T6-TJyG-)pt3xhhpS_mAQ-O_(CK1ba(9wt5x{~Fe zho%y8Jg4C0zKIN_XLs}5z9V-k!AnZMv9dVJW|w%u(sv8Fw5i=v93;e(m2u%%J}3D! z-oH-ovt)p&u(vc(Jhx$M~PGq164Z_mP)`>#GAE=kPQB6+0&naH6^E0`Viga zAL$SL**O6;7au*ir)2;3WGS4bAEf!KA$_<~2^JN6UZ_7(tsf&PL}!WNWy-Pa@rG^X z*-j$fKuL86Y^Vk2JUM)sI8VP)E6RG|P2j;zv3E5nrrLSG=K_7kFA0bXIr1^DS1s;6 zJ3llm87faMJ+WrkQ^xZfvHoSk72keR{SQK5?Lsz!>%XKQ;W>{R>a)BPlaH+F6T zH2}7wO)G0Iu+dZBm_QETtY1w)l_2-*+fe0%@hP%}gD0e`-5{o-mJ0l$o7! zIYG29TJQ}A&>-0f3B;yLjbej}LPr;9HUjl&UE?GkH*4MM+<)&T}Y({lCH_AVp0y|g9q81Y?5YQML8(+}YpBsihZ5qV)g@J~AM;3mx(0&hs z<{7mBBJq3rn1Vo-A_zFF#jM3ppT4Sr$TV&)7wjZ1p$9>?*2Mx6fT1oW?mlRjDF)sm zH(#)c!d+LASl}P=(5oLH_khV5vF(kPiFVub;$H`i;$sAvE_wE8+f zoyBYkt0x`8bhB8Pm}VKKCxZa2V)*pf1EX(Q~R#E8!l;WEiBnzfD1+!1Tuf1u@XscP6%aNf zHECg&Rxeqdjkw@XSe%(JsP}9*Uj12cpdVM!xElZ;C>^!TfXx5KaQ@Fq@Bat1@c(VP|4a-2n}+p&qJ?Lm{X5J|$IOV! z#>o7iVP-xW$-iN?e`k093uSfv7i^X8->_B2zhkScf1_3Z?*}s*{ofHzR%Tq*KYU8TIErbNZ<4S)kn0|OP2!GL%H>EJsapp~l+z%3`o?Hien58_q>`! z6F^-SrKFw%u`i&17|geaQWLN`N12ut=9)%e%vJ)-_nJp9G=1MEX(M-v8eGAb1U&u% zAW$e2cw-6*z)yV-U=b5eT{bZO3!~_>y(KR_GZTH~v-;MD>C{I9biMzgifF^;b;I( z&Thb<0DO~ZT~4k5@?vh^5eEV%`iOzVm42kdrLuQJ>`FfA@I#YbyD$j;(5Cz(;?@pC8^H;+1^xhj z`Jwd;{3A`-2bX{06;`mM?~_*$>f)0(uyN8`oX{Dkci*^LH^zAEJy@icKV7JQ0M-I;9n8y-AAcK)~0m0m_p7lx>4_iNe2~PQ}TK4%A zm>sOHLdl>*-D+8q!}|Id#IQXt4n-PM$Nau}oL&r~X|@@S)7nfkZ_Sfw7%2ugb8r6m zvUzi|nV~b??0%YFsj~?)mD>LaLIcCt2h%rpvA8=ji5R2f+{c5yCcFAZQ2UtU2$Dd) zInG1NML9IKrc1vl)7sVadpSTpvRs>jS)lH78JL_s{@R&gO}7-QGQ#m~sX#i$s1u&D z_FU&p%%+(c!R-Yb9>Vj$hW|rHXC@OX`w?0(u7ISTrLx2LFDD^p*|T_FU<*%nPi1@# z2+D$)dsaJZ!+^Es%Ss-ZnK8=~)2whX9+^q!8;xWna;5-l-d=f&rEjpysaxb7+P`vy zc;H$s<#M)MifL`e9>b3O>)N22K4fl?#+SwyUauP!*|>QaXt(f{HQVUJ`u7)|wj$7D z7NH&YP4_NhR?!UQyfD!Bn>CX{!rq(=RxojB4Vbmb4xvz|u4xj@CG(3ABTB$IS+9`f zF@)OssU{F#+bSsDT`C0kWr52*)0I|nYCfQ`>3bB&3a7ig9uJ}NWF*~erctd41iwvCjQnCe5&&(bPw%FM`CeANz_s3f!DvmzI<^|&K zlP62P)k^o{sU7Z&QG%B%lc?tssC4i^r+jla$WUmMpN_>yvpLTnAy&xr`}U8*Xk#Fi z%S*Y1@84vwyKUDz0|`?2n}O=6<%yum-9=9cPJ7`3|~qVKOJ#N9+l!%^c`bunLW~~`s`pkezD6de|UPKA0F+97m?vGLglg&u(K%BkWPNf!08^5Gx zbP;+ui#xFik+TCnF`qG&f$kKa9#WM%3JG;>Rgbb}fzsxFNk2O*&0g&r-qsx9gk1h; zlK-v^t8-S5{`#G!#&b)k9ShJxtGs^5uvCF)^l}!KTN5kltHf>&mmCD{hIJqkaZDS* zqMki!Qn;(C&wblY;tRW!C24p4UiINDXno7v^{qTOub8SKrEQUrSbs8I;X^Ra@|8%3 zpX#c+vPwy@hK59_#pL3F)94V^|Kt7+yaeUgkpFI{aknJ|Q6|guxyTr+oyN%^A-ntR z&ZFs;pT6P3vZOOR_neUnUeLuD`Sx<0IbQqMe2Wshfe=6m@kZ>jF>}w=4BSaRx?TQ3>%sL$0(L8^oQb9C!349K>r#j$NaGI$(As&7BHDcg6SQZ z;ym5ey?}$kVeF>w%33T6GLTjUBTTU%uHUj3D?t-W03Vsas+71O*XGrLzR@))XmRqU zv~q*p8Nm)td=H^*9T4*4HMBmfP3j8MNc3F=m5A)>9}W`OZU@p=m?FM9b6^&wH!F=r zALh@ZhZY7EZEvI8kC@&01=>D4oG9gY$(U6I%;7VF>!Yu{#qom3^1X96DhKsF9B)>5 zN#}{quP`Fzq&D`FLpft2BAK8Tl)!-2!0dBNvpYR^S;~B0n~BlY zInDXanegzEa50&b=mP3F!c}opa7QH{X^(I#&;#5)H@auiKK7>;K9BT zju3M4U%qwHH5`}j@h?jKj#IAmC6y@q?J03QJ*YBuP17!YZ^d9sPGmlC*zr%D`biJ1 zFOZfn8vHqj?dkieP=#mx?f;zMM2 z%B7qS9Glr$Lv1KC!^lT5gi>Tc{%3?`cg-GmPoRz(R;$jzX({Lv^kg(2c73Z!Y zKoG?>3WXPzZ&|Vy^BJ5Bhm_LoJvq{ew?yP}&R%bjH(E@?Tr$xU26wg6Q{r@(e5UyP z(sNdH2=bVl77}Zy31lqJfNb2}4)h_O=sZPZh!hFzF2#?=lmoZA-T>L6+YUg2R%7JI zLL>~RYL6C3F!M7Xt~WK;=-OqDui@ug14p7!Gi8v0UsUi>A%kYm3l7NH5RV|^kN{s} z=z;qb`8{qOE5pyN;^LKVQpx1D<`^bZ?w|t0`>C1Ou-;8$%&95*c$rlWr#m?W%(THu zlSAQuoYA94xR8S4EVG@Th92~WbmqWWacp*6-5F>5=ZNnSU%gunF$R@%BX1Vxq`RbA zhbXfyt5tP5_ucZ;8R6p zweec@Ut7Cs-FiPHYjXnBu}ZxJ!>0rS*>XTLM6>Yq4aQYnAzZ71SG6!R(kXtpVpaqG zxCtxYR$Trm#&C9i`k=tKPq7B7>F#Vxwc42(X~DP{5`4_n4Qyl=dsDZ#=0?rOvARB< z4!NKsud`kV`FUbE@I2Jq>4DkTNJnIsp+PMp$E=j%?UAKulGm!2XE!!4PR_P&;yL(C z*?u$FjMSoqi@bhq^0F?r^${*!sl`FSUO7V%>7GW4NI+eA3)wJEMr;1OIi#j?ydtOW z1DH)iBc)C&w6_2rXXxPnAVi~LBzxrv>1xj;6yO~$`E|Rf|LfuainH0Na-$JtNdz)bXEup7|s_BOp zM%gvnO`j{%`Uq?w#qQk26&&oWosoq5N6sB3Mb@t^qwEv=`onK{;(Zn_D`PhBVI=my z+^WBx-iT(Q$i)&jE-121r^xj!6pYoS#q7S`s|Tm$dzkQz0vwt-jlRp4V|7J!e7 zaX)Gwc`&^pH>SQnsF7u|PM$PY5O?ioKPMd8G%Xk`XKOSNZ{|{YpUtMgB%$WzHHDVg zkfC%W&J}Q$%WN9z9%cwZ0S>5E`w?Udaib@;iQm`gZtz;I7Z^U#ff`Sq`gq!bO^CB; zVw2LSrwm=g>S{LPEq2~0cb=XC_-8&-gp<35KJYtCx?57*oPvC&%A910@4@e(5(8aR{Z1BLn4j>2F zwqriH6l4x-sIbgsFEDkr)JmR3)X3e-*w14{Olaw3Q-WDwJB+M_4wmpK zw#C>l{oTs0he4g|PrmY*l?0bvMEnJ##ohp_klK$p_(^BOPU7L)NHtqxp!!P= zvkm!=cf);+p7AO;ZIJ-|U@-Mjl5p;@Sv+TytF?#|THCfEaM2l+z!bR=aU_|J-M-bI zx4B1&j2*3G_r15)_0f0~r6xk!1@%rc=*~sEYR|`(Pq%!5qN9rfG2c6H5xozac~mCE zZz*-cK%=ftXc*}I-j2mtC2OMRQC)=n1~F3waS)UEmwrYn*14-(#$OfIfIWt(T=414 z()sOEd;{`7lZjo?(6-)1Kq|yRLPpvPA8>AoexMfa-VX)2QQ9`0Ll``?qUXAieVj0A z7!@z3gP=>rEaSQ=DTeY<>^RaLjiFF3j1{vD)Rt8gzHhratVdDqZIJDNBPXOJ@s;gc z5de%^nxXyJ_E3M`S{4FZF}+s0aR+xJlp=W`j3S64bWDsVL$m zy}2OaWSg_HL^)Z+srcttV3;Q`B)3&?0BzF&yX8@aI`a9UZw+r}x@iI$1eLjE7<6|` z>sdJOK;)vS5N{mLxZA-wR9Z25;1HDFdFeH>F;(&nT>%j>s!)!8MaPYh zCd)T|D^~FeS4_yDvyX}-g|N#|5<9UjK5o8Ds^^$4c}U<<`Ly-E%OX+bvu)1#PO)wFsz5_J?7mYK zMkoB3TN7oDP?>pIR&sbClq$)!8_T;-ATOWEQ6t6=J4O((X>KiN_Hxbw^dWZ&Kai7H ze9L8~Y1&`ZYBGG^kZHuBpa13t5E?jz1NhXiBF0(%+fV|EaZg;g|1p>4^^{TGis;X)$((Oz1TsBg|@_fATE&3XxI=P%bGaTS(_4B73?PD*9FRDrpB`9 zVZXY(Oq9%W6@+7h*oTW`QoD{%ghL5&j(GTF6=^t*>e-0Qj8Bjmt1IB)DpHQ3zu|1v zJa>WPvnw6@AX^jTg)*5B1%pQIQPI5GV;EVBpU!=E zdbr98wN*<-*{9RRT@P=8?Cb@1?H3&^;KS5z6#$fD;8*7l=&bTgYjo}7<&LM}(OK|O zMMYMG)Zb_%9!cD^8tdgfeUF7EOhjf?_0nn=;Pl}(DQZY8^6%fA9iKq6YT7PH7`E0k zPQM={F-e(H9+sJ&O+}rlr$$4chl_sDgqBG)8eZ*nE`>gkEH`FeL#4*$J69bNWBF7i zZB$g;x_mx;^Qil@?F*5lFa4yk%M>$3u*Z5}N|_JvvwAsmJ~X@6)!}#7={zfP9A@yj z+c|ru&%YK{e1?jd6MWGjXv2(A$FmaLd4pSRaD{h^!|Tq$WwLj1`c|2S_`W{PV9Lfu z8l`b{4Lp+MWPlq(!Yh|BF}e^}d;?#DZ9q#wMnP!9xYI@cXsNPHBOHBqM7!_Eexz!sw`Bct zCnVfXy1X-8-ItL_$YmsICOwVh93y%PE_e{lQ>hdrCm!y2^K*0Bu|%8qXT$Dt)!FyDf^+x@PIO12(Gk>Z|0*DaM3F`q9UG&by48W) z$SA8)H_|hF@hAJzG`T@9Ba|g6*AYnmLg@LFLZf~LZSuTl&+n%;npgrf{rcrmTCU0@ zV*YxD1&nGS1A(e?NeAS|3VLQoO4t-XyJQd}C$1~iXt69{lWBz;@mn{CD{BPxaY7g= z9X(jV-qt8sf*f;?cqgq)%>vm7XU(@=`7}+RB1-`2p(G|Wj#rFAu-mfIL-Gk(%L}6V z&o_zgY7?<{IkN|1_cPS&7L7yAL>A?=h1%3hTVxX4A#fbxje|RH0dWkONpnLq-d?>U zHG9j|yFHl7ubZ&!jWH+{{~|AZ zI(&zE!svCfwX0Q)v34kMYEH~t7Bzc{kf{enPp4fo;4qJCQ#360De{D0PHf0kZV9=W zrCxGf4vvb>X$Q2!ehC7Ood86nb$HH88k5y-k2nQ{uSR*#z;_Y6eu5R+gH zw-I!Hc~9N-44k<9@O1i~{e2bcVQ6;ea6jm+ zW<}Z(+`j9_x_Bk4$&z;tde^Ql#Qt#EWi|(Sy9w&5yIUNQrcbD}Z&)PrUE5z=Jm5k% zy0P%vC~;MDrp56#bJ4teA)4w@Fl-t;98h5+l>rvKtu2R1>&bgT5kF!@2kbcE(-47n zd*2)6%5TN7A+6mjM(8nK^lYn%Y(bj_GdblnaZ_Fgy9ape+N~+BZRmw|oU^_pU!M*W5jA~~&sWL&!Q)8zeP*&yr9ZCPnZ_**2bIa`xOS74aUSi`uUe!vi1{YVBP8W<8u3}Cz z^eTeNG1z>c(Ua>iK(XZ0C^iFiO5U;24;!wYpMS zb%y4)%%t|6<{E43U{?2hwAb>@lzB6so{?L?;GlmWIGLy~+bQHH)hD0d5avL;$Z17}uxm4bjYY~6XkXk}B zB-e_!a9*cKsp6zGSi!rTxg?+S>DyZb>NHvw>mvTlvF{;|GPC4eXMcw-Qe3*(>CIVM zUoWOohhUyjieXl5DgPLRY*p0kI4Fx4F}=vcmawd_r#O@B*1->b^(B+p8)-dLz>{L- zV6t_2m#`8MMDa-$X6=ETzo3&(EbgdybxFwZvQ$>*ijcOGUcWNLGeFZS?;e5QC33k_ z>4_;jhdZ+k+b5eS48{dolWryX0P)JyQc2$h;aujz1*6!q4-#i-0ZO*~AfqB`_*p95 z9h35rqYq_NlzG@8So}~)4+!X&BBO!wW|gU}}-Ht$rC;<(jh7 z;rg2rsH$&hOaTvJaXNG0qi((le=eXB$}dJxBmyh5aSPT#kf02Swv|ZptKo?y<^l>k z@Z`$yIAMswF73PQk7U6qJ4@)GhI@pz#BIB#*<*pHND@g{E_U9S zVzvF#&79}-0>JYnUUL%5JaWdD^{Fnnmiao-P<6_r#6@fku>LwGBez^HtOfmwnyx)R zd83QF(@&cs_C)wBmYlpDPc56m*z9OsRGKH29=seW;W3)ra+D-%s1pWe zV)K=v+P=H#bY8T)FxRZB2fU4Zh&Kj-S;2+Y|WqlUr-xDz~G2k-&`AIX=(f>;?CPv1;`uy4ZKQ8?LQt@ z0Xn*Wl7?kuW%?gtl$e-U>HpVT2jY!X6|I_w#S*E%5wZNF?}MgG5EadLB**Kg?HK`q z7I68VGe<@y5A<`+KLJ;?1h=rk7ibO~-2dvtVM}EC&YSaizIAF#=h0@<;$!(s{b>!T z19T{l{85!75EMB81qlTq8BEbBYQPAojsGz^&hGTIje z1THx#IUzAQHV+v8&0|No z50UOH^`$Ea%*@~#fo+OUQ5wPLZBayxNL&7wTUk^{Zmca*BmpEK?x1p*22IfEHJl<40Eh0Toex++E`aJG%P4^EVz(G5 zkS~*WJS)J`yVOA2d3Ts<@f*u1{5iBYLhaNwix`mZ{oEa4;XyPu%i0gkAm{b$tPfcgZEXvN^CpF9BS6BvBq#wTx{(EA^i&R;=a zt%S=}dYzs^L_~mc5Tqcn@%}*c^7fx!T+@gFj!q(`<$$u_Aov7eA4oy%`?lcFpUXO8 z8{Izjz&~3m!2?l%q`BzAgLEL;EtBWG(Ag-P=AAlGw5Tsbs^~e( zJ(}OXiI?#(ZmMKBGIUc|)O#>3^QulB%%6&B|8$m!NqdZ>HA91na!fE2bZyKbto~t; zW?@&LIFLYMAP+RSa6aS9@xuh27pJLa@^T`?%>5k{Ln>{Z&sudGA({b2dLWYu!%B@>PC;gkrqozPe3>-6lLQip!W-0|H z&3a~hrA*&F7ETN$3M6}PE!7?R@hw2k+SVGs5s>31gWAsp+hpB6K zef{4#cJ*i@q9^X9trQ95@2OV56;!XZy8va5`t8$Lo^l#5w(EAJNLi>cXP6(ag5wxk zhpZ&h&^p%+id3L^`?EZ51sii=w3kC0v`8LinJvPw zA-OOp_(_7^F%TJHq&lELB1VYlJu~@cBh#{MrK%nMg#4*R8i;=l+Pa|%O2NlSC!%f4BOHU$ zZQDSkm!W0@<;wHSw=%Aw6eq|F3Kvkp zqezr>0}e*8G(WX-?Ah+Uid)_Al`U{nGhV)t`zdwcq+MB5vnwm({K8*7H_nOAt+i71J7Uru;YB0LYHWrutx`N?!f<&|!z0ntt z+I5x%8kuktBJhV4>GnjPJ3X&E`$1dtn~S&kVe|Gmv!6%}gE9y$smwCwWg3YqvhTU# zu!?*qAe-fAc~6OwRPVpiJX8>@jL=;uT*hxt##@{FH@DVnPzW5#4ua8*9URtvjHr2^ zCw8F#+k0`nr_yl9H*pj^RMm{ua}mcXaFZV~6C!qD{Fyx8jHO zg+YRGo<;dFE9#AQ14+{>mQe{OW|b8{?su*vsZgq;UAoXZJ@||HvT??gzSQ;!Lclt3 zpw)dsA*?I;XICt1m zG@R@VOCTqZQn1i;{q@LU0DeJw8V4~4Z)uaXT)K6=mEU7$5-XG?7;&nZpZ74fk(&%9 zFqlYbJ1eLM{@`65}|*Za`*vV@+YaF9cN`1r14jiP~{0;v$56ZKx&Qp>n*HWA>XF6HFQX zkPzd7N7c3pP5WxB*sEEVM|j)xbzwzV=BLwAQ<@rz#Qv`IcP~t^L5ePWNnNIlwz*@e zSMjILb$(?mL&P6!XM_@J!;U=S9Bf@9Gu>EaV_oi2$vlT5DlT#`3&BDCr+0^dj*)Vk z%u16<;Kjrw2__Ojjq4i}9~DaTiyTF9xP|>O-ztl0U$6Jl8FDw-m&hF~sZzaz4vHh_%AiwD2chmSuUE(tgnL?I<| z|1^4Oum;=GHTTraGr@gg)1X2wdVC@MWI_bbH9ozxP1_3wJ>Hnm#r@U6EN5Ujvfsmg z^AR!U!H7l%;Q-PeUMHy@QS=4lXFEV7&NScke5$-$eEYczs>N@1?M$BkGvd+pIQGEN z`+N{@+Qx%i10yjC*+$0B`94X;$PPWg1d>{`9up<|XuP5Y14m4&nx@2^mHkqy3~SBa z??o<@aB(ZS*u-88l%V@(d~~X*MU_TPbEOXtNMST(^KhIIUlK64^|!fTM$;tO5}oY2 z-5g@djP1n~OsOA088~9d5e>}Z~Vt~82Y&RB3%! zY#W{rO#HhF{qV{5cj>8&u4W{iB#YQAN$1VG@@ft#N{@LH*pdxd@I%^<@Kyzw@4LNo zTzDf{^vD7IQ?tD*62jDnl&BvZ-tx6V#q>Bv!x@OaI5)O*pdx60{8wR88wI$cpZwGz(Tl#F^@tJ2YY!&G|Q8rUr(%GL>=u-ozyGr6rhNuL#OZ$UkDM$YXb zdz`0XQd2Bmna1j1fofAR&nxq^1gyeIX2XO4NHm=3rTKuQcrM%OQ@$ z-{R{xj>sMFcO@RL6{cb;i}+?Tf~RmvP{GIUW6>EPrD^%vJ@XVREA!O<;C>BKy`+gF0W3-J$7Lx~`A@PUqx=3)wT$4gpXC^Kubp zP4Wh?!#1}pGHtQzy1S&5ve&1Jl+6~XMa-n~}3*m_0@PJr;(Y(u%R$wde01(`k^UX!t0Dp@}~N#90U z1iJ}^<-9|gbN_664C>VPy2?SPL$Js(#1vE`?TMFpIqb82rutNO<)J+}pjLlr(A06Or{Rv?8x*dYSbuuXP(sP$CUT1luZ3 zT-F}1RpUk1g^qkxj=A+B%JT0LZuN*tlz6S_qh%D*G8@V9sX+Vn+T+5+T_#UZY7Bq` z$UACu%DHl8QMAJIA;+CYCZ=ncTi{vV68nR)_4bG_KPJhidfVueUN$IFstWiCJX!#_ zg#|=YgupyN#Pwy&5Oe#IiuaS-I0zoauQ+&CgJFxl^F*l-w*)K{PEDjf(csu;Hu{E` z(sqi%`eK}xv!ddl);4K(mXl%Wai_Kus}a z!9{eb6U5%)`}DraHunL0CFHmxTvOzdrRq?nf(*@^1kr7^&F z){s!FJ$mf-u>%(bgXcqG6zOXFBGG);E5O(}x= z`twKMcLG>vBDM2HmUOWZU?3;r>nT!8-C7IIgnKuNd}BeD|ErZNfr{$LqQ)df8A%ij z$db@7fIx!$eNhCJMWV6_h!KK~fUFI6v$l%SusDDbMCp!310f>fLX1HZWf2!}39=Xj zA&5#;1W^_tK@_HbH#+dks#+ty?XVkIQQ4nyEIs#?!0Jb-Hq)_tGxG0 zWzj8Fjy0#T{?6|-E^0_i!=)W*y;CgudQ|(>b=6yrPTx8u)ae=JJH@x?vB^Iwt7q>n z)|4a{Sxa?S7Tq9gQ+@rOEsl(ld~#jCBHZBYGxIjWc1+uqo|LZ`Z|ZP$ZO zeOKpfZHQ`{I&#GD{&4-G%mpUbEsTq=Ji6=cITVtv7Nw<@SN$ZkHo+40)2L!*I+>UJ zsNxaSrgd1e&9@*yYG&HqyjQ#KXD9PIr-9vRI|A67zBdYmuJ?kR-<%!3bJx-5adzom z&0jwVFHEnph@+$EUyLr^Po);Mjf*!=UE(YIOMQNZE=^j@0FgfV&lSW zq#|=+)1OC+n2V3xRy|tP-<*)sD30h&U+mKK*7lvMi~45vCzcwt zdEI%xZm+aqpOz@oblr)=2dhh4k0i=I+M(y-qS;Agc(3k%Pi7T;(TyIya>`NTSYx`w z?KMWr53H{<_hQ@l5c&kmJ|h*wMAb{;LbN&i*BDI}T3kcsl7xYWwpZ zaZA;EA561bQkRrjJ(#Vx@!G?ZcbA@BaJfHg?)1BDDf_7SNUh(m>Ga93`@TU(zoU!*zJRe$f9^xb;8 zo`_|j;i`mnOJvr_tk(UHY~D_C*nKj;M6FPGuQ$}Ez&Uu?6|p4$hsR-u=47zN8Q(XR z4`*~q{p?qo1Q~7K7C%jUZF}qb8KT{zq7QE-O2 zcw*L&@M5ITzzoW|UJuRCerHfSS~VniG}X1GSx5C-jbw`@Fn4fQWPf0? z78AT`e_oWt*vcSY;(fh+>vz^axmdlMe9A-b%Z{cT_1L%=zdZ|O$FH?VZvK2}Ou5ti zv@{p@u=3kI%&19x5_+Y1?et8~gjD0Z6?RkPZk=<&wncUuE=*#mNi)md-{WcOT_k_z zFRypon&mJ}_PDh8{)OrjvdQB6?!KEwyBltP?pAl30Fp~|Mm28n@jWh4hD3ZekQMZr1$(*#f$tsB@G_6^SZJ&33F@S zF=p=dGbtzj$Qx#$^k$Rq-Pgr}ue#M4+9*KM#Ew;V}}t_J_x-e|vU%@~MdK zCyAHcC2 ze zRq=en;LVXaGA;9k`fv3KYfN`p6+KOSySqZ(akwegtso`GHgC-rM~C%A8L>mx&N=Rz zF;8=DWWmRg#~*07>cm_c?a3Y4yk%5-PBAz$MI<&y?0sr?Y~LH$374{AK| zfzsoM4~kEGIJ-D3b#+&e5i~@6@XMkR|1dL)jID#!g70kvMuQ8s}AR$hJdc|pw6F3F(^%oeG zmlzd11;vbAGQ!^%17vZ`932;Io*UNEB64U>3`Q{Uw6c z98=;Zz!le4ff>bvB$N*Y5R8_4_>6NQ1=n@_?~GBnQlnBatu#t2g*2snuzYI_@%Prq zzp}W0b>CdP~tio+@}YY=mHmM66R$>ikbv zUEJ-w=GsSxh4~3Zq5!eL#62ijA^^XU{(yHx$ z1gap4YthK7A24_lCk26mF&U0?RH5P<(JL9orL&1LgsXKqL5AWu%U$1{Aj24hfpIj) z`c1^qBp0j`WGKtv41~j3z6})Q9zG5wC=`cq7z^QW8sm?br5O@xi*xk~`8bl}Cnw5C zmOvpKff5i7r};RB#xNL%p%9KD7=B-9f~05&hhs1f;m;95fuZqzK;sO<_cKlq{5c0e zppq}6SQ5hF1Z0CE2$t_Z3P%_Q!r?f7925%sg=9hSLO6sUR{)2ie7j&KNl3=9a9c2M z{Ix)U5Qq8#<_+=-OA!bpBcb?1KpgPr2xoDIuMb2J4&yLr&T)!`e1($;%eRYDG&EkY z;81>_QH+GzA}oVIZ3&j<#{o)kg#-Bd7%0D>6ixBx1EnY^c2N?6)*#BzP!2;G3W3H! zF(eNMVw^Q<--gyI zjY7Eu?1GR_ah9SW8(b3~Dp&~&B%^5-Ix`R$KevN@A8HHI8uOa?L-~0P$Y}o9fQ;e$3dmS=oGeN#1pl&# zRk(xPiePDgvKEb7LI5{jb~XEbow06kPOGO}~FSNS(5 CW39sg diff --git a/liboctave/UMFPACK/UMFPACK/Doc/QuickStart.tex b/liboctave/UMFPACK/UMFPACK/Doc/QuickStart.tex new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/QuickStart.tex @@ -0,0 +1,1029 @@ +%------------------------------------------------------------------------------- +% The QuickStart.tex file. +%------------------------------------------------------------------------------- + +\documentclass[11pt]{article} + +\newcommand{\m}[1]{{\bf{#1}}} % for matrices and vectors +\newcommand{\tr}{^{\sf T}} % transpose + +\topmargin 0in +\textheight 9in +\oddsidemargin 0pt +\evensidemargin 0pt +\textwidth 6.5in + +\begin{document} + +\author{Timothy A. Davis \\ +Dept. of Computer and Information Science and Engineering \\ +Univ. of Florida, Gainesville, FL} +\title{UMFPACK Version 4.4 Quick Start Guide} +\date{Jan. 28, 2005} +\maketitle + +%------------------------------------------------------------------------------- +\begin{abstract} + UMFPACK is a set of routines for solving unsymmetric sparse linear + systems, $\m{Ax}=\m{b}$, using the Unsymmetric-pattern MultiFrontal method + and direct sparse LU factorization. It is written in ANSI/ISO C, with a + MATLAB interface. UMFPACK relies on the Level-3 + Basic Linear Algebra Subprograms (dense matrix multiply) for its + performance. This code works on Windows and many versions of Unix (Sun + Solaris, Red Hat Linux, IBM AIX, SGI IRIX, and Compaq Alpha). + This is a ``quick start'' guide for Unix users of the C interface. +\end{abstract} +%------------------------------------------------------------------------------- + +UMFPACK Version 4.4 (Jan. 28, 2005), Copyright\copyright 2005 by Timothy A. +Davis. All Rights Reserved. Refer to the UMFPACK User Guide +for the License. See \newline +http://www.cise.ufl.edu/research/sparse/umfpack +for the code and full documentation. + +%------------------------------------------------------------------------------- +\section{Overview} +%------------------------------------------------------------------------------- + +UMFPACK is a set of routines for solving systems of linear +equations, $\m{Ax}=\m{b}$, when $\m{A}$ is sparse and unsymmetric. +The sparse matrix $\m{A}$ can be square or rectangular, singular +or non-singular, and real or complex (or any combination). Only square +matrices $\m{A}$ can be used to solve $\m{Ax}=\m{b}$ or related systems. +Rectangular matrices can only be factorized. + +UMFPACK Version 4.3 is a built-in routine in MATLAB 7.1, used by the forward and +backslash operator, and the {\tt lu} routine. MATLAB 6.5 used Version 4.0. +The following is a short +introduction to Unix users of the C interface of UMFPACK. + +%------------------------------------------------------------------------------- + +The C-callable UMFPACK library consists of 32 user-callable routines and one +include file. Twenty-eight of the routines come in four versions, with +different sizes of integers and for real or complex floating-point numbers. +This Quick Start Guide assumes you are working with real matrices +(not complex) and with {\tt int}'s as integers (not {\tt long}'s). +Refer to the User Guide for information about the complex and +long integer versions. The include file {\tt umfpack.h} +must be included in any C program that uses UMFPACK. + +For more details, see: +{\em A column pre-ordering strategy for the unsymmetric-pattern multifrontal method}, +Davis, T. A., +ACM Trans. Math. Software, vol 30. no 2, 2004, pp. 165-195, and +{\em Algorithm 832: {UMFPACK}, an unsymmetric-pattern multifrontal method}, +same issue, pp. 196-199. + +%------------------------------------------------------------------------------- +\section{Primary routines, and a simple example} +%------------------------------------------------------------------------------- + +Five primary UMFPACK routines are required to factorize $\m{A}$ or +solve $\m{Ax}=\m{b}$. An overview of the primary features of the routines +is given in Section~\ref{Primary}. +Additional routines are available for passing a different column ordering +to UMFPACK, changing default parameters, manipulating sparse matrices, +getting the LU factors, save and loading the LU factors from a file, +computing the determinant, +and reporting results. See the User Guide for more information. + +\begin{itemize} +\item {\tt umfpack\_di\_symbolic}: + + Pre-orders the columns of $\m{A}$ to reduce fill-in and performs a + symbolic analysis. + Returns an opaque {\tt Symbolic} object as a {\tt void *} + pointer. The object contains the symbolic analysis and is needed for the + numerical factorization. + +\item {\tt umfpack\_di\_numeric}: + + Numerically scales and then factorizes a sparse matrix + $\m{PAQ}$, $\m{PRAQ}$, or $\m{PR}^{-1}\m{AQ}$ into the product $\m{LU}$, + where + $\m{P}$ and $\m{Q}$ are permutation matrices, $\m{R}$ is a diagonal + matrix of scale factors, $\m{L}$ is lower triangular with unit diagonal, + and $\m{U}$ is upper triangular. Requires the + symbolic ordering and analysis computed by {\tt umfpack\_di\_symbolic}. + Returns an opaque {\tt Numeric} object as a + {\tt void *} pointer. The object contains the numerical factorization and + is used by {\tt umfpack\_di\_solve}. + +\item {\tt umfpack\_di\_solve}: + + Solves a sparse linear system ($\m{Ax}=\m{b}$, $\m{A}\tr\m{x}=\m{b}$, or + systems involving just $\m{L}$ or $\m{U}$), using the numeric factorization + computed by {\tt umfpack\_di\_numeric}. + +\item {\tt umfpack\_di\_free\_symbolic}: + + Frees the {\tt Symbolic} object created by {\tt umfpack\_di\_symbolic}. + +\item {\tt umfpack\_di\_free\_numeric}: + + Frees the {\tt Numeric} object created by {\tt umfpack\_di\_numeric}. + +\end{itemize} + +The matrix $\m{A}$ is represented in compressed column form, which is +identical to the sparse matrix representation used by MATLAB. It consists +of three arrays, where the matrix is {\tt m}-by-{\tt n}, +with {\tt nz} entries: + +{\footnotesize +\begin{verbatim} + int Ap [n+1] ; + int Ai [nz] ; + double Ax [nz] ; +\end{verbatim} +} + +All nonzeros are entries, but an entry may be numerically zero. The row indices +of entries in column {\tt j} are stored in + {\tt Ai[Ap[j]} ... {\tt Ap[j+1]-1]}. +The corresponding numerical values are stored in + {\tt Ax[Ap[j]} ... {\tt Ap[j+1]-1]}. + +No duplicate row indices may be present, and the row indices in any given +column must be sorted in ascending order. The first entry {\tt Ap[0]} must be +zero. The total number of entries in the matrix is thus {\tt nz = Ap[n]}. +Except for the fact that extra zero entries can be included, there is thus a +unique compressed column representation of any given matrix $\m{A}$. + +Here is a simple main program, {\tt umfpack\_simple.c}, that illustrates the +basic usage of UMFPACK. + +{\footnotesize +\begin{verbatim} + #include + #include "umfpack.h" + + int n = 5 ; + int Ap [ ] = {0, 2, 5, 9, 10, 12} ; + int Ai [ ] = { 0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4} ; + double Ax [ ] = {2., 3., 3., -1., 4., 4., -3., 1., 2., 2., 6., 1.} ; + double b [ ] = {8., 45., -3., 3., 19.} ; + double x [5] ; + + int main (void) + { + double *null = (double *) NULL ; + int i ; + void *Symbolic, *Numeric ; + (void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null) ; + (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null) ; + umfpack_di_free_symbolic (&Symbolic) ; + (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null) ; + umfpack_di_free_numeric (&Numeric) ; + for (i = 0 ; i < n ; i++) printf ("x [%d] = %g\n", i, x [i]) ; + return (0) ; + } +\end{verbatim} +} + +The {\tt Ap}, {\tt Ai}, and {\tt Ax} arrays represent the matrix +\[ +\m{A} = \left[ +\begin{array}{rrrrr} + 2 & 3 & 0 & 0 & 0 \\ + 3 & 0 & 4 & 0 & 6 \\ + 0 & -1 & -3 & 2 & 0 \\ + 0 & 0 & 1 & 0 & 0 \\ + 0 & 4 & 2 & 0 & 1 \\ +\end{array} +\right]. +\] +and the solution is $\m{x} = [1 \, 2 \, 3 \, 4 \, 5]\tr$. The program uses +default control settings and does not return any statistics about the ordering, +factorization, or solution ({\tt Control} and {\tt Info} are both +{\tt (double *) NULL}). + +For routines to manipulate a simpler ``triplet-form'' data structure for your +sparse matrix $\m{A}$, refer to the UMFPACK User Guide. + +%------------------------------------------------------------------------------- +\section{Synopsis of primary C-callable routines} +\label{Synopsis} +%------------------------------------------------------------------------------- + +The matrix $\m{A}$ is {\tt m}-by-{\tt n} with {\tt nz} entries. +The optional {\tt umfpack\_di\_defaults} routine loads the default control +parameters into the {\tt Control} array. The settings can then be modified +before passing the array to the other routines. Refer to Section~\ref{Primary} +for more details. + +{\footnotesize +\begin{verbatim} + #include "umfpack.h" + int status, sys, n, m, nz, Ap [n+1], Ai [nz] ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], Ax [nz], X [n], B [n] ; + void *Symbolic, *Numeric ; + + status = umfpack_di_symbolic (m, n, Ap, Ai, Ax, &Symbolic, Control, Info) ; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info) ; + status = umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ; + umfpack_di_free_symbolic (&Symbolic) ; + umfpack_di_free_numeric (&Numeric) ; + umfpack_di_defaults (Control) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\section{Installation} +\label{Install} +%------------------------------------------------------------------------------- + +You will need to install both UMFPACK v4.4 and AMD v1.1 (or AMD v1.0) to use UMFPACK. +The {\tt UMFPACK} and {\tt AMD} subdirectories must be placed side-by-side +within the same parent directory. AMD is a stand-alone package that +is required by UMFPACK. UMFPACK can be compiled without the +BLAS but your performance will be much less than what it should be. + +System-dependent configurations are in the {\tt AMD/Make} +and {\tt UMFPACK/Make} directories +(Note that {\tt UMFPACK/Make} is a symbolic link to {\tt AMD/Make}). +You can edit the {\tt Make.include} +file in those directories to customize the compilation. The default +settings will work on most systems, except that UMFPACK will be compiled so +that it does not use the BLAS. Sample configuration files are provided +for Linux, Sun Solaris, SGI IRIX, IBM AIX, and the DEC/Compaq Alpha. + +To compile and install both packages, +go to the UMFPACK directory and type {\tt make}. This will compile the +libraries ({\tt AMD/Lib/libamd.a} and {\tt UMFPACK/Lib/libumfpack.a}). +A demo of the AMD ordering routine will be compiled and tested in +the {\tt AMD/Demo} directory, and five demo programs will then be +compiled and tested in the {\tt UMFPACK/Demo} directory. +The outputs of these demo programs will then be compared with output +files in the distribution. Expect to see a few differences, such as +residual norms, compile-time control settings, and perhaps memory usage +differences. The AMD and MATLAB mexFunctions for +use in MATLAB will also be compiled. If you do not have MATLAB, +type {\tt make lib} instead. + +If you compile UMFPACK and AMD and then later change the {\tt Make.include} +file or your system-specific configuration file such as {\tt Make.linux}, +then you should type {\tt make purge} and then {\tt make} to recompile. + +Here are the various parameters that you can control in your +{\tt Make.include} file: + +\begin{itemize} +\item {\tt CC = } your C compiler, such as {\tt cc}. +\item {\tt RANLIB = } your system's {\tt ranlib} program, if needed. +\item {\tt CFLAGS = } optimization flags, such as {\tt -O}. +\item {\tt CONFIG = } configuration settings, for the BLAS, memory allocation + routines, and timing routines. +\item {\tt LIB = } your libraries, such as {\tt -lm} or {\tt -lblas}. +\item {\tt RM =} the command to delete a file. +\item {\tt MV =} the command to rename a file. +\item {\tt MEX =} the command to compile a MATLAB mexFunction. +\item {\tt F77 =} the command to compile a Fortran program (optional). +\item {\tt F77FLAGS =} the Fortran compiler flags (optional). +\item {\tt F77LIB =} the Fortran libraries (optional). +\end{itemize} + +The {\tt CONFIG} string can include combinations of the following; +most deal with how the BLAS are called: +\begin{itemize} +\item {\tt -DNBLAS} if you do not have any BLAS at all. +\item {\tt -DCBLAS} if you have the C-BLAS. +\item {\tt -DNSUNPERF} if you are on Solaris but do not have the Sun + Performance Library. +\item {\tt -DNSCSL} if you on SGI IRIX but do not have the SCSL BLAS library. +\item {\tt -DLONGBLAS} if your BLAS can take {\tt long} integer input + arguments. +\item Options for controlling how C calls the Fortran BLAS: + {\tt -DBLAS\_BY\_VALUE}, {\tt -DBLAS\_NO\_UNDERSCORE}, + and {\tt -DBLAS\_CHAR\_ARG}. These are set automatically for Windows, + Sun Solaris, SGI Irix, Red Hat Linux, Compaq Alpha, and + AIX (the IBM RS 6000). +\item {\tt -DGETRUSAGE} if you have the {\tt getrusage} function. +\item {\tt -DLP64} if you are compiling in the LP64 model (32 bit {\tt int}'s, + 64 bit {\tt long}'s, and 64 bit pointers). +\item {\tt -DNUTIL} if you wish to compile the MATLAB-callable + UMFPACK mexFunction with the {\tt mxMalloc}, {\tt mxRealloc} + and {\tt mxFree} routines, instead of the undocumented (but + superior) {\tt utMalloc}, {\tt utRealloc}, and {\tt utFree} + routines. +\item {\tt -DNPOSIX} if you do not have the POSIX-compliant + {\tt sysconf} and {\tt times} routines. +\item {\tt -DNRECIPROCAL} controls a trade-off between speed and accuracy. + This is off by default (speed preferred over accuracy) except when + compiling for MATLAB. +\end{itemize} + +When you compile your program that uses the C-callable UMFPACK library, +you need to add the both {\tt UMFPACK/Lib/libumfpack.a} and +{\tt AMD/Lib/libamd.a} +libraries, and you need to tell your compiler to look in the +directories {\tt UMFPACK/Include} and {\tt AMD/Include} for include +files. See {\tt UMFPACK/Demo/Makefile} for an example. +You do not need to directly include any AMD include files in your +program, unless you directly call AMD routines. You only need the +\begin{verbatim} +#include "umfpack.h" +\end{verbatim} +statement, as described in Section~\ref{Synopsis}. + +%------------------------------------------------------------------------------- +\newpage +\section{The primary UMFPACK routines} +\label{Primary} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_di\_symbolic} + +{\footnotesize +\begin{verbatim} +int umfpack_di_symbolic +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +Purpose: + + Given nonzero pattern of a sparse matrix A in column-oriented form, + umfpack_di_symbolic performs a column pre-ordering to reduce fill-in + (using COLAMD or AMD) and a symbolic factorization. This is required + before the matrix can be numerically factorized with umfpack_di_numeric. + + For the following discussion, let S be the submatrix of A obtained after + eliminating all pivots of zero Markowitz cost. S has dimension + (n_row-n1-nempty_row) -by- (n_col-n1-nempty_col), where + n1 = Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS], + nempty_row = Info [UMFPACK_NEMPTY_ROW] and + nempty_col = Info [UMFPACK_NEMPTY_COL]. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0. + + Int Ap [n_col+1] ; Input argument, not modified. + + Ap is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the sparse matrix A. Column j of + the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)]. The first + entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold for all + j in the range 0 to n_col-1. The value nz = Ap [n_col] is thus the + total number of entries in the pattern of the matrix A. nz must be + greater than or equal to zero. + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + The nonzero pattern (row indices) for column j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j + must be in ascending order, and no duplicate row indices may be present. + Row indices must be in the range 0 to n_row-1 (the matrix is 0-based). + + double Ax [nz] ; Optional input argument, not modified. + + The numerical values of the sparse matrix A. The nonzero pattern (row + indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and + the corresponding numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. Used only by the 2-by-2 strategy to + determine whether entries are "large" or "small". You do not have to + pass the same numerical values to umfpack_di_numeric. If Ax is not + present (a (double *) NULL pointer), then any entry in A is assumed to + be "large". + + void **Symbolic ; Output argument. + + **Symbolic is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Symbolic object (if successful), or (void *) NULL if + a failure occurred. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Only the primary parameters are listed below: + + Control [UMFPACK_STRATEGY]: This is the most important control + parameter. It determines what kind of ordering and pivoting + strategy that UMFPACK should use. It is new to Version 4.1 + There are 4 options: + + UMFPACK_STRATEGY_AUTO: This is the default. The input matrix is + analyzed to determine how symmetric the nonzero pattern is, and + how many entries there are on the diagonal. It then selects one + of the following strategies. Refer to the User Guide for a + description of how the strategy is automatically selected. + + UMFPACK_STRATEGY_UNSYMMETRIC: Use the unsymmetric strategy. COLAMD + is used to order the columns of A, followed by a postorder of + the column elimination tree. No attempt is made to perform + diagonal pivoting. The column ordering is refined during + factorization. This strategy was the only one provided with + UMFPACK V4.0. + + In the numerical factorization, the + Control [UMFPACK_SYM_PIVOT_TOLERANCE] parameter is ignored. A + pivot is selected if its magnitude is >= + Control [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the + largest entry in its column. + + UMFPACK_STRATEGY_SYMMETRIC: Use the symmetric strategy (new to + Version 4.1). In this method, the approximate minimum degree + ordering (AMD) is applied to A+A', followed by a postorder of + the elimination tree of A+A'. UMFPACK attempts to perform + diagonal pivoting during numerical factorization. No refinement + of the column preordering is performed during factorization. + + In the numerical factorization, a nonzero entry on the diagonal + is selected as the pivot if its magnitude is >= Control + [UMFPACK_SYM_PIVOT_TOLERANCE] (default 0.001) times the largest + entry in its column. If this is not acceptable, then an + off-diagonal pivot is selected with magnitude >= Control + [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry + in its column. + + UMFPACK_STRATEGY_2BY2: a row permutation P2 is found that places + large entries on the diagonal. The matrix P2*A is then + factorized using the symmetric strategy, described above. + Refer to the User Guide for more information. + + Control [UMFPACK_2BY2_TOLERANCE]: a diagonal entry S (k,k) is + considered "small" if it is < tol * max (abs (S (:,k))), where S a + submatrix of the scaled input matrix, with pivots of zero Markowitz + cost removed. + + Control [UMFPACK_SCALE]: This parameter is new to V4.1. See + umfpack_numeric.h for a description. Only affects the 2-by-2 + strategy. Default: UMFPACK_SCALE_SUM. + + double Info [UMFPACK_INFO] ; Output argument, not defined on input. + + Contains statistics about the symbolic analysis. If a (double *) NULL + pointer is passed, then no statistics are returned in Info (this is not + an error condition). The entire Info array is cleared (all entries set + to -1) and then the following statistics are computed (only the + primary statistics are listed): + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + Each column of the input matrix contained row indices + in increasing order, with no duplicates. Only in this case + does umfpack_di_symbolic compute a valid symbolic factorization. + For the other cases below, no Symbolic object is created + (*Symbolic is (void *) NULL). + + UMFPACK_ERROR_n_nonpositive + + n is less than or equal to zero. + + UMFPACK_ERROR_invalid_matrix + + Number of entries in the matrix is negative, Ap [0] is nonzero, + a column has a negative number of entries, a row index is out of + bounds, or the columns of input matrix were jumbled (unsorted + columns or duplicate entries). + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to perform the symbolic analysis. If the + analysis requires more than 2GB of memory and you are using + the 32-bit ("int") version of UMFPACK, then you are guaranteed + to run out of memory. Try using the 64-bit version of UMFPACK. + + UMFPACK_ERROR_argument_missing + + One or more required arguments is missing. + + UMFPACK_ERROR_internal_error + + Something very serious went wrong. This is a bug. + Please contact the author (davis@cise.ufl.edu). + + Info [UMFPACK_SIZE_OF_UNIT]: the number of bytes in a Unit, + for memory usage statistics below. + + Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]: the amount of memory (in Units) + required for umfpack_di_symbolic to complete. This count includes + the size of the Symbolic object itself, which is also reported in + Info [UMFPACK_SYMBOLIC_SIZE]. + + Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]: an estimate of the final size (in + Units) of the entire Numeric object (both fixed-size and variable- + sized parts), which holds the LU factorization (including the L, U, + P and Q matrices). + + Info [UMFPACK_PEAK_MEMORY_ESTIMATE]: an estimate of the total amount of + memory (in Units) required by umfpack_di_symbolic and + umfpack_di_numeric to perform both the symbolic and numeric + factorization. This is the larger of the amount of memory needed + in umfpack_di_numeric itself, and the amount of memory needed in + umfpack_di_symbolic (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]). The + count includes the size of both the Symbolic and Numeric objects + themselves. It can be a very loose upper bound, particularly when + the symmetric or 2-by-2 strategies are used. + + Info [UMFPACK_FLOPS_ESTIMATE]: an estimate of the total floating-point + operations required to factorize the matrix. This is a "true" + theoretical estimate of the number of flops that would be performed + by a flop-parsimonious sparse LU algorithm. It assumes that no + extra flops are performed except for what is strictly required to + compute the LU factorization. It ignores, for example, the flops + performed by umfpack_di_numeric to add contribution blocks of + frontal matrices together. If L and U are the upper bound on the + pattern of the factors, then this flop count estimate can be + represented in MATLAB (for real matrices, not complex) as: + + Lnz = full (sum (spones (L))) - 1 ; % nz in each col of L + Unz = full (sum (spones (U')))' - 1 ; % nz in each row of U + flops = 2*Lnz*Unz + sum (Lnz) ; + + The actual "true flop" count found by umfpack_di_numeric will be + less than this estimate. + + Info [UMFPACK_LNZ_ESTIMATE]: an estimate of the number of nonzeros in + L, including the diagonal. Since L is unit-diagonal, the diagonal + of L is not stored. This estimate is a strict upper bound on the + actual nonzeros in L to be computed by umfpack_di_numeric. + + Info [UMFPACK_UNZ_ESTIMATE]: an estimate of the number of nonzeros in + U, including the diagonal. This estimate is a strict upper bound on + the actual nonzeros in U to be computed by umfpack_di_numeric. + + Info [UMFPACK_SYMBOLIC_TIME]: The CPU time taken, in seconds. + + Info [UMFPACK_STRATEGY_USED]: The ordering strategy used: + UMFPACK_STRATEGY_SYMMETRIC, UMFPACK_STRATEGY_UNSYMMETRIC, or + UMFPACK_STRATEGY_2BY2. +\end{verbatim} +} + + +%------------------------------------------------------------------------------- +\newpage +\subsection{umfpack\_di\_numeric} + +{\footnotesize +\begin{verbatim} +int umfpack_di_numeric +( + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + void *Symbolic, + void **Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +Purpose: + + Given a sparse matrix A in column-oriented form, and a symbolic analysis + computed by umfpack_di_symbolic, the umfpack_di_numeric routine performs the + numerical factorization, PAQ=LU, PRAQ=LU, or P(R\A)Q=LU, where P and Q are + permutation matrices (represented as permutation vectors), R is the row + scaling, L is unit-lower triangular, and U is upper triangular. This is + required before the system Ax=b (or other related linear systems) can be + solved. umfpack_di_numeric can be called multiple times for each call to + umfpack_di_symbolic, to factorize a sequence of matrices with identical + nonzero pattern. Simply compute the Symbolic object once, with + umfpack_di_symbolic, and reuse it for subsequent matrices. + umfpack_di_numeric safely detects if the pattern changes, and sets an + appropriate error code. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int Ap [n_col+1] ; Input argument, not modified. + + This must be identical to the Ap array passed to umfpack_di_symbolic. + The value of n_col is what was passed to umfpack_di_symbolic (this is + held in the Symbolic object). + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + This must be identical to the Ai array passed to umfpack_di_symbolic. + + double Ax [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + The numerical values of the sparse matrix A. The nonzero pattern (row + indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and + the corresponding numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. + + void *Symbolic ; Input argument, not modified. + + The Symbolic object, which holds the symbolic factorization computed by + umfpack_di_symbolic. The Symbolic object is not modified by + umfpack_di_numeric. + + void **Numeric ; Output argument. + + **Numeric is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Numeric object (if successful), or (void *) NULL if + a failure occurred. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Only the primary parameters are listed below: + + Control [UMFPACK_PIVOT_TOLERANCE]: relative pivot tolerance for + threshold partial pivoting with row interchanges. In any given + column, an entry is numerically acceptable if its absolute value is + greater than or equal to Control [UMFPACK_PIVOT_TOLERANCE] times + the largest absolute value in the column. A value of 1.0 gives true + partial pivoting. If less than or equal to zero, then any nonzero + entry is numerically acceptable as a pivot (this is changed from + Version 4.0). Default: 0.1. + + Smaller values tend to lead to sparser LU factors, but the solution + to the linear system can become inaccurate. Larger values can lead + to a more accurate solution (but not always), and usually an + increase in the total work. + + Control [UMFPACK_SYM_PIVOT_TOLERANCE]: This parameter is new to V4.1. + If diagonal pivoting is attempted (the symmetric or symmetric-2by2 + strategies are used) then this parameter is used to control when the + diagonal entry is selected in a given pivot column. The absolute + value of the entry must be >= Control [UMFPACK_SYM_PIVOT_TOLERANCE] + times the largest absolute value in the column. A value of zero + will ensure that no off-diagonal pivoting is performed, except that + zero diagonal entries are not selected if there are any off-diagonal + nonzero entries. + + If an off-diagonal pivot is selected, an attempt is made to restore + symmetry later on. Suppose A (i,j) is selected, where i != j. + If column i has not yet been selected as a pivot column, then + the entry A (j,i) is redefined as a "diagonal" entry, except that + the tighter tolerance (Control [UMFPACK_PIVOT_TOLERANCE]) is + applied. This strategy has an effect similar to 2-by-2 pivoting + for symmetric indefinite matrices. If a 2-by-2 block pivot with + nonzero structure + + i j + i: 0 x + j: x 0 + + is selected in a symmetric indefinite factorization method, the + 2-by-2 block is inverted and a rank-2 update is applied. In + UMFPACK, this 2-by-2 block would be reordered as + + j i + i: x 0 + j: 0 x + + In both cases, the symmetry of the Schur complement is preserved. + + Control [UMFPACK_SCALE]: This parameter is new to V4.1. Version 4.0 + did not scale the matrix. Note that the user's input matrix is + never modified, only an internal copy is scaled. + + There are three valid settings for this parameter. If any other + value is provided, the default is used. + + UMFPACK_SCALE_NONE: no scaling is performed. + + UMFPACK_SCALE_SUM: each row of the input matrix A is divided by + the sum of the absolute values of the entries in that row. + The scaled matrix has an infinity norm of 1. + + UMFPACK_SCALE_MAX: each row of the input matrix A is divided by + the maximum the absolute values of the entries in that row. + In the scaled matrix the largest entry in each row has + a magnitude exactly equal to 1. + + Scaling is very important for the "symmetric" strategy when + diagonal pivoting is attempted. It also improves the performance + of the "unsymmetric" strategy. + + Default: UMFPACK_SCALE_SUM. + + double Info [UMFPACK_INFO] ; Output argument. + + Contains statistics about the numeric factorization. If a + (double *) NULL pointer is passed, then no statistics are returned in + Info (this is not an error condition). The following statistics are + computed in umfpack_di_numeric (only the primary statistics are listed): + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + Numeric factorization was successful. umfpack_di_numeric + computed a valid numeric factorization. + + UMFPACK_WARNING_singular_matrix + + Numeric factorization was successful, but the matrix is + singular. umfpack_di_numeric computed a valid numeric + factorization, but you will get a divide by zero in + umfpack_di_solve. For the other cases below, no Numeric object + is created (*Numeric is (void *) NULL). + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to complete the numeric factorization. + + UMFPACK_ERROR_argument_missing + + One or more required arguments are missing. + + UMFPACK_ERROR_invalid_Symbolic_object + + Symbolic object provided as input is invalid. + + UMFPACK_ERROR_different_pattern + + The pattern (Ap and/or Ai) has changed since the call to + umfpack_di_symbolic which produced the Symbolic object. + + Info [UMFPACK_NUMERIC_SIZE]: the actual final size (in Units) of the + entire Numeric object, including the final size of the variable + part of the object. Info [UMFPACK_NUMERIC_SIZE_ESTIMATE], + an estimate, was computed by umfpack_di_symbolic. The estimate is + normally an upper bound on the actual final size, but this is not + guaranteed. + + Info [UMFPACK_PEAK_MEMORY]: the actual peak memory usage (in Units) of + both umfpack_di_symbolic and umfpack_di_numeric. An estimate, + Info [UMFPACK_PEAK_MEMORY_ESTIMATE], was computed by + umfpack_di_symbolic. The estimate is normally an upper bound on the + actual peak usage, but this is not guaranteed. With testing on + hundreds of matrix arising in real applications, I have never + observed a matrix where this estimate or the Numeric size estimate + was less than the actual result, but this is theoretically possible. + Please send me one if you find such a matrix. + + Info [UMFPACK_FLOPS]: the actual count of the (useful) floating-point + operations performed. An estimate, Info [UMFPACK_FLOPS_ESTIMATE], + was computed by umfpack_di_symbolic. The estimate is guaranteed to + be an upper bound on this flop count. The flop count excludes + "useless" flops on zero values, flops performed during the pivot + search (for tentative updates and assembly of candidate columns), + and flops performed to add frontal matrices together. + + Info [UMFPACK_LNZ]: the actual nonzero entries in final factor L, + including the diagonal. This excludes any zero entries in L, + although some of these are stored in the Numeric object. The + Info [UMFPACK_LU_ENTRIES] statistic does account for all + explicitly stored zeros, however. Info [UMFPACK_LNZ_ESTIMATE], + an estimate, was computed by umfpack_di_symbolic. The estimate is + guaranteed to be an upper bound on Info [UMFPACK_LNZ]. + + Info [UMFPACK_UNZ]: the actual nonzero entries in final factor U, + including the diagonal. This excludes any zero entries in U, + although some of these are stored in the Numeric object. The + Info [UMFPACK_LU_ENTRIES] statistic does account for all + explicitly stored zeros, however. Info [UMFPACK_UNZ_ESTIMATE], + an estimate, was computed by umfpack_di_symbolic. The estimate is + guaranteed to be an upper bound on Info [UMFPACK_UNZ]. + + Info [UMFPACK_NUMERIC_TIME]: The CPU time taken, in seconds. +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\subsection{umfpack\_di\_solve} + +{\footnotesize +\begin{verbatim} +int umfpack_di_solve +( + int sys, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + double X [ ], + const double B [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +Purpose: + + Given LU factors computed by umfpack_di_numeric (PAQ=LU, PRAQ=LU, or + P(R\A)Q=LU) and the right-hand-side, B, solve a linear system for the + solution X. Iterative refinement is optionally performed. Only square + systems are handled. Singular matrices result in a divide-by-zero for all + systems except those involving just the matrix L. Iterative refinement is + not performed for singular matrices. + + In the discussion below, n is equal to n_row and n_col, because only + square systems are handled. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int sys ; Input argument, not modified. + + Defines which system to solve. (') is the linear algebraic transpose. + + sys value system solved + + UMFPACK_A Ax=b + UMFPACK_At A'x=b + UMFPACK_Pt_L P'Lx=b + UMFPACK_L Lx=b + UMFPACK_Lt_P L'Px=b + UMFPACK_Lt L'x=b + UMFPACK_U_Qt UQ'x=b + UMFPACK_U Ux=b + UMFPACK_Q_Ut QU'x=b + UMFPACK_Ut U'x=b + + Iterative refinement can be optionally performed when sys is any of + the following: + + UMFPACK_A Ax=b + UMFPACK_At A'x=b + + For the other values of the sys argument, iterative refinement is not + performed (Control [UMFPACK_IRSTEP], Ap, Ai, and Ax are ignored). + + Int Ap [n+1] ; Input argument, not modified. + Int Ai [nz] ; Input argument, not modified. + double Ax [nz] ; Input argument, not modified. + + If iterative refinement is requested (Control [UMFPACK_IRSTEP] >= 1, + Ax=b or A'x=b is being solved, and A is nonsingular), then + these arrays must be identical to the same ones passed to + umfpack_di_numeric. The umfpack_di_solve routine does not check the + contents of these arguments, so the results are undefined if Ap, Ai, Ax, + are modified between the calls the umfpack_di_numeric and + umfpack_di_solve. These three arrays do not need to be present (NULL + pointers can be passed) if Control [UMFPACK_IRSTEP] is zero, or if a + system other than Ax=b or A'x=b is being solved, or if A is + singular, since in each of these cases A is not accessed. + + double X [n] ; Output argument. + + The solution to the linear system, where n = n_row = n_col is the + dimension of the matrices A, L, and U. + + double B [n] ; Input argument, not modified. + + The right-hand side vector, b, stored as a conventional array of size n + (or two arrays of size n for complex versions). This routine does not + solve for multiple right-hand-sides, nor does it allow b to be stored in + a sparse-column form. + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_di_numeric. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. + + Control [UMFPACK_IRSTEP]: The maximum number of iterative refinement + steps to attempt. A value less than zero is treated as zero. If + less than 1, or if Ax=b or A'x=b is not being solved, or + if A is singular, then the Ap, Ai, and Ax arguments are not + accessed. Default: 2. + + double Info [UMFPACK_INFO] ; Output argument. + + Contains statistics about the solution factorization. If a + (double *) NULL pointer is passed, then no statistics are returned in + Info (this is not an error condition). The following statistics are + computed in umfpack_di_solve (only the primary statistics are listed): + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + The linear system was successfully solved. + + UMFPACK_WARNING_singular_matrix + + A divide-by-zero occurred. Your solution will contain Inf's + and/or NaN's. Some parts of the solution may be valid. For + example, solving Ax=b with + + A = [2 0] b = [ 1 ] returns x = [ 0.5 ] + [0 0] [ 0 ] [ Inf ] + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to solve the linear system. + + UMFPACK_ERROR_argument_missing + + One or more required arguments are missing. The B and X + arguments are always required. Info and Control are not + required. Ap, Ai and Ax are required if Ax=b or + A'x=b is to be solved, the (default) iterative + refinement is requested, and the matrix A is nonsingular. + + UMFPACK_ERROR_invalid_system + + The sys argument is not valid, or the matrix A is not square. + + UMFPACK_ERROR_invalid_Numeric_object + + The Numeric object is not valid. + + Info [UMFPACK_SOLVE_FLOPS]: the number of floating point operations + performed to solve the linear system. This includes the work + taken for all iterative refinement steps, including the backtrack + (if any). + + Info [UMFPACK_SOLVE_TIME]: The time taken, in seconds. +\end{verbatim} +} + + +%------------------------------------------------------------------------------- +\newpage + +\subsection{umfpack\_di\_free\_symbolic} +{\footnotesize +\begin{verbatim} +void umfpack_di_free_symbolic +( + void **Symbolic +) ; + +Purpose: + + Deallocates the Symbolic object and sets the Symbolic handle to NULL. + +Arguments: + + void **Symbolic ; Input argument, deallocated and Symbolic is + set to (void *) NULL on output. +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{umfpack\_di\_free\_numeric} + +{\footnotesize +\begin{verbatim} +void umfpack_di_free_numeric +( + void **Numeric +) ; + +Purpose: + + Deallocates the Numeric object and sets the Numeric handle to NULL. + +Arguments: + + void **Numeric ; Input argument, deallocated and Numeric is + set to (void *) NULL on output. +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{umfpack\_di\_defaults} + +{\footnotesize +\begin{verbatim} +void umfpack_di_defaults +( + double Control [UMFPACK_CONTROL] +) ; + +Purpose: + + Sets the default control parameter settings. + +Arguments: + + double Control [UMFPACK_CONTROL] ; Output argument. + + Control is set to the default control parameter settings. +\end{verbatim} +} +\end{document} diff --git a/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.bib b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.bib new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.bib @@ -0,0 +1,322 @@ +@string{TOMS = "ACM Trans. Math. Softw."} +@string{SIMAX = "SIAM J. Matrix Anal. Applic."} +@string{SINUM = "SIAM J. Numer. Anal."} +@string{SIAMJSC = "SIAM J. Sci. Comput."} +@string{SIAMJSSC = "SIAM J. Sci. Statist. Comput."} +@string{IJNME = "Internat. J. Numer. Methods Eng."} +@string{SIAMJADM = "SIAM J. Alg. Disc. Meth."} + +@article{AmestoyDavisDuff96, + author={Amestoy, P. R. and Davis, T. A. and Duff, I. S.}, + title={An approximate minimum degree ordering algorithm}, + journal=SIMAX, + year={1996} + ,volume={17} + ,number={4} + ,pages={886-905}} + +@article{AmestoyDavisDuff03, + author={Amestoy, P. R. and Davis, T. A. and Duff, I. S.}, + title={Algorithm 837: {AMD}, an approximate minimum degree ordering algorithm}, + journal=TOMS, + year={2004} + ,volume={30} + ,number={3} + ,pages={381-388}} + +@techreport{AmestoyDavisDuff03_user, + author={Amestoy, P. R. and Davis, T. A. and Duff, I. S.}, + title={{AMD} Version 1.0 User Guide}, + institution={CISE Dept., Univ. of Florida}, + year={2003} + ,number={TR-03-011} + ,address={Gainesville, FL} + ,note={www.cise.ufl.edu/tech-reports.} + } + +@article{Davis03, + author={Davis, T. A.}, + title={A column pre-ordering strategy for the unsymmetric-pattern multifrontal method}, + journal=TOMS, + year={2004} + ,volume={30} + ,number={2} + ,pages={165-195}} + +@article{Davis03_algo, + author={Davis, T. A.}, + title={Algorithm 832: {UMFPACK}, an unsymmetric-pattern multifrontal method}, + journal=TOMS, + year={2004} + ,volume={30} + ,number={2} + ,pages={196-199}} + +@techreport{Davis03_umf, + author={Davis, T. A.}, + title={{UMFPACK} Version 4.4 User Guide}, + institution={Univ. of Florida, CISE Dept.}, + year={2004} + ,number={TR-04-003} + ,address={Gainesville, FL} + ,note={(www.cise.ufl.edu/tech-reports)} + } + +@techreport{Davis03_umfquick, + author={Davis, T. A.}, + title={{UMFPACK} Version 4.4 Quick Start Guide}, + institution={Univ. of Florida, CISE Dept.}, + year={2004} + ,number={TR-04-005} + ,address={Gainesville, FL} + ,note={(www.cise.ufl.edu/tech-reports)} + } + +@article{DavisDuff97, + author={Davis, T. A. and Duff, I. S.}, + title={An unsymmetric-pattern multifrontal method for sparse {LU} factorization}, + journal=SIMAX, + year={1997} + ,volume={18} + ,number={1} + ,pages={140-158}} + +@article{DavisDuff99, + author={Davis, T. A. and Duff, I. S.}, + title={A combined unifrontal/multifrontal method for unsymmetric sparse matrices}, + journal=TOMS, + volume={25}, + number={1}, + pages={1-19}, + year={1999}} + +@article{SuperLU99, + author={Demmel, J. W. and Eisenstat, S. C. and Gilbert, J. R. and Li, X. S. and Liu, J. W. H.}, + title={A supernodal approach to sparse partial pivoting}, + journal=SIMAX, + year={1999} + ,volume={20} + ,number={3} + ,pages={720-755} + ,note={www.netlib.org} + } + +@article{ACM679a, + author={Dongarra, J. J. and Du Croz, J. and Duff, I. S. and Hammarling, S.}, + title={A set of level-3 basic linear algebra subprograms}, + journal=TOMS, + year={1990} + ,volume={16} + ,number={1} + ,pages={1--17}} + +@article{netlib, + author={Dongarra, J. J. and Grosse, E.}, + title={Distribution of mathematical software via electronic mail}, + journal={Comm. ACM}, + year={1987} + ,volume={30} + ,pages={403-407} + ,note={www.netlib.org} + } + +@article{Duff78b, + author={Duff, I. S. and Reid, J. K.}, + year={1978}, + title={Algorithm 529: Permutations to Block Triangular Form}, + journal=TOMS, + volume={4}, + annote={f}, + number={2}, + pages={189-192}, + keywords={102 ordering block triangular form}} + +@article{Duff81b, + author={Duff, I. S.}, + year={1981}, + title={Algorithm 575: Permutations for a Zero-Free Diagonal}, + journal=TOMS, + annote={f}, + volume={7}, + pages={387-390}, + keywords={ordering, zero-free diagonal}} + +@techreport{GotoVandeGeijn02, + author = {Goto, K. and van de Geijn, R.}, + title = {On Reducing {TLB} Misses in Matrix Multiplication, {FLAME} Working Note 9}, + institution={The University of Texas at Austin, Department of Computer Sciences}, + number={TR-2002-55}, + month={Nov.}, + year={2002}} + +@article{GeorgeNg85, + author={George, A. and Ng, E. G.}, + year={1985}, + title={An Implementation of {G}aussian Elimination with + Partial Pivoting for Sparse Systems}, + journal=SIAMJSSC, + volume={6}, + number={2}, + pages={390-409}} + +@article{GeorgeNg87, + author={George, A. and Ng, E. G.}, + year={1987}, + title={Symbolic Factorization for Sparse {G}aussian Elimination + with Partial Pivoting}, + journal={SIAM J. Sci. Statist. Comput.}, + volume={8}, + number={6}, + pages={877-898}} + +@article{GilbertMolerSchreiber, + author={Gilbert, J. R. and Moler, C. and Schreiber, R.}, + title={Sparse matrices in {MATLAB}: design and implementation}, + journal=SIMAX, + year={1992} + ,volume={13} + ,number={1} + ,pages={333-356}} + +@article{GilbertPeierls88, + author={Gilbert, J. R. and Peierls, T.}, + year={1988}, + title={Sparse Partial Pivoting in Time Proportional to Arithmetic Operations}, + journal={SIAM J. Sci. Statist. Comput.}, + volume={9}, + pages={862-874}} + +@article{Gustavson78, + author={Gustavson, F. G.}, + year={1978}, + title={Two Fast Algorithms for Sparse Matrices: Multiplication and Permuted Transposition}, + journal=TOMS, + volume={4}, + number={3}, + pages={250-269}} + +@techreport{Larimore98, + author={Larimore, S. I.}, + title={An approximate minimum degree column ordering algorithm}, + institution={Univ. of Florida, CISE Dept.}, + year={1998} + ,number={TR-98-016} + ,address={Gainesville, FL} + ,note={www.cise.ufl.edu/tech-reports}} + +@article{DavisGilbertLarimoreNg00, + author={Davis, T. A. and Gilbert, J. R. and Larimore, S. I. and Ng, E. G.}, + title={A column approximate minimum degree ordering algorithm}, + journal=TOMS, + year={2004} + ,volume={30} + ,number={3} + ,pages={353-376}} + +@article{DavisGilbertLarimoreNg00_algo, + author={Davis, T. A. and Gilbert, J. R. and Larimore, S. I. and Ng, E. G.}, + title={Algorithm 836: {COLAMD}, a column approximate minimum degree ordering algorithm}, + journal=TOMS, + year={2004} + ,volume={30} + ,number={3} + ,pages={377-380}} + +@INCOLLECTION{GilbertNg93, + author = {J. R. Gilbert and E. G. Ng}, + editor = {A. George and J. R. Gilbert and J. W.H. Liu}, + year = 1993, + title = {Predicting Structure in Nonsymmetric Sparse Matrix Factorizations}, + booktitle = {Graph Theory and Sparse Matrix Computation}, + series = {Volume 56 of the {IMA} Volumes in Mathematics and its Applications}, + pages = {107-139}, + publisher = {Springer-Verlag} +} + + +@techreport{ATLAS, + author={Whaley, R. C and Petitet, A. and Dongarra, J. J.}, + title={Automated Emperical Optimization of Software and the {ATLAS} Project}, + institution={Computer Science Department, The University of Tennessee}, + year={2000} + ,number={LAPACK Working Note 147} + ,month={September} + ,note={www.netlib.org/atlas} + } + +@article{DaydeDuff99, + author = "M. J. Dayd\'{e} and I. S. Duff", + title = "The {RISC} {BLAS}: A Blocked Implementation of Level 3 {BLAS} for {RISC} Processors", + journal = TOMS, + volume = "25", + number = "3", + month = {Sept.}, + year ="1999" + } + + +@article{ardd:89, + author = {M. Arioli and J. W. Demmel and I. S. Duff}, + year = "1989", + title = {Solving sparse linear systems with sparse backward error}, + journal = SIMAX, + volume = {10}, + pages = {165-190} +} + + +@article{DavisHager99, + author={Davis, T. A. and Hager, W. W.}, + title={Modifying a sparse {C}holesky factorization}, + journal=SIMAX, + year={1999} + ,volume={20} + ,number={3} + ,pages={606-627} + } + + +@article{dusc:96, + author = {I. S. Duff and J. A. Scott}, + title = {The design of a new frontal code for solving sparse unsymmetric systems}, + journal = TOMS, + year = "1996", + volume = "22", + number = "1", + pages = "30-45" + } + + +@article{Duff78a, + author={Duff, I. S. and Reid, J. K.}, + year={1978}, + title={An Implementation of {T}arjan's Algorithm for the Block Triangularization of a Matrix}, + journal=TOMS, + volume={4}, + number={2}, + pages={137-147} + } + +@book{GeorgeLiu, + author={George, A. and Liu, J. W. H.}, + year={1981}, + title={Computer Solution of Large Sparse Positive Definite Systems}, + publisher={Englewood Cliffs, New Jersey: Prentice-Hall} + } + +@article{GilbertNgPeyton94, + author={Gilbert, J. R. and Ng, E. G. and Peyton, B. W.}, + title={An efficient algorithm to compute row and column counts for sparse {C}holesky factorization}, + journal=SIMAX, + year={1994} + ,volume={15} + ,number={4} + ,pages={1075-1091} + } + +@techreport{DuffGrimesLewis87b, + author={Duff, I. S. and Grimes, R. G. and Lewis, J. G.}, + year={1987}, + title={Users' Guide for the Harwell-Boeing Sparse Matrix Test Collection}, + institution={AERE Harwell Laboratory, United Kingdom Atomic Energy Authority}} + diff --git a/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.pdf b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.pdf new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3509a087aaa02c852019078214a7a9f8c32751f4 GIT binary patch literal 401941 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 koTOqDNn;iMUZ(CumA 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 P^OsTU+jorRShfEL+rzDo diff --git a/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed1 b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed1 new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed1 @@ -0,0 +1,33 @@ +/INCLUDE umfpack_col_to_triplet.h/r ../Include/umfpack_col_to_triplet.h +/INCLUDE umfpack_defaults.h/r ../Include/umfpack_defaults.h +/INCLUDE umfpack_free_numeric.h/r ../Include/umfpack_free_numeric.h +/INCLUDE umfpack_free_symbolic.h/r ../Include/umfpack_free_symbolic.h +/INCLUDE umfpack_get_lunz.h/r ../Include/umfpack_get_lunz.h +/INCLUDE umfpack_get_numeric.h/r ../Include/umfpack_get_numeric.h +/INCLUDE umfpack_get_symbolic.h/r ../Include/umfpack_get_symbolic.h +/INCLUDE umfpack_get_scale.h/r ../Include/umfpack_get_scale.h +/INCLUDE umfpack_numeric.h/r ../Include/umfpack_numeric.h +/INCLUDE umfpack_qsymbolic.h/r ../Include/umfpack_qsymbolic.h +/INCLUDE umfpack_report_control.h/r ../Include/umfpack_report_control.h +/INCLUDE umfpack_report_info.h/r ../Include/umfpack_report_info.h +/INCLUDE umfpack_report_matrix.h/r ../Include/umfpack_report_matrix.h +/INCLUDE umfpack_report_numeric.h/r ../Include/umfpack_report_numeric.h +/INCLUDE umfpack_report_perm.h/r ../Include/umfpack_report_perm.h +/INCLUDE umfpack_report_status.h/r ../Include/umfpack_report_status.h +/INCLUDE umfpack_report_symbolic.h/r ../Include/umfpack_report_symbolic.h +/INCLUDE umfpack_report_triplet.h/r ../Include/umfpack_report_triplet.h +/INCLUDE umfpack_report_vector.h/r ../Include/umfpack_report_vector.h +/INCLUDE umfpack_simple.c/r ../Demo/umfpack_simple.c +/INCLUDE umfpack_solve.h/r ../Include/umfpack_solve.h +/INCLUDE umfpack_scale.h/r ../Include/umfpack_scale.h +/INCLUDE umfpack_symbolic.h/r ../Include/umfpack_symbolic.h +/INCLUDE umfpack_timer.h/r ../Include/umfpack_timer.h +/INCLUDE umfpack_tictoc.h/r ../Include/umfpack_tictoc.h +/INCLUDE umfpack_transpose.h/r ../Include/umfpack_transpose.h +/INCLUDE umfpack_triplet_to_col.h/r ../Include/umfpack_triplet_to_col.h +/INCLUDE umfpack_wsolve.h/r ../Include/umfpack_wsolve.h +/INCLUDE umfpack_load_numeric.h/r ../Include/umfpack_load_numeric.h +/INCLUDE umfpack_load_symbolic.h/r ../Include/umfpack_load_symbolic.h +/INCLUDE umfpack_save_numeric.h/r ../Include/umfpack_save_numeric.h +/INCLUDE umfpack_save_symbolic.h/r ../Include/umfpack_save_symbolic.h +/INCLUDE umfpack_get_determinant.h/r ../Include/umfpack_get_determinant.h diff --git a/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed2 b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed2 new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.sed2 @@ -0,0 +1,3 @@ +/[/][*]/d +/[*][/]/d +/INCLUDE umfpack/d diff --git a/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.stex b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.stex new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Doc/UserGuide.stex @@ -0,0 +1,2673 @@ +%------------------------------------------------------------------------------- +% The UserGuide.stex file. Processed into UserGuide.tex via sed. +%------------------------------------------------------------------------------- + +\documentclass[11pt]{article} + +\newcommand{\m}[1]{{\bf{#1}}} % for matrices and vectors +\newcommand{\tr}{^{\sf T}} % transpose +\newcommand{\he}{^{\sf H}} % complex conjugate transpose +\newcommand{\implies}{\rightarrow} + +\topmargin 0in +\textheight 9in +\oddsidemargin 0pt +\evensidemargin 0pt +\textwidth 6.5in + +\begin{document} + +\author{Timothy A. Davis \\ +Dept. of Computer and Information Science and Engineering \\ +Univ. of Florida, Gainesville, FL} +\title{UMFPACK Version 4.4 User Guide} +\date{Jan. 28, 2005} +\maketitle + +%------------------------------------------------------------------------------- +\begin{abstract} + UMFPACK is a set of routines for solving unsymmetric sparse linear + systems, $\m{Ax}=\m{b}$, using the Unsymmetric MultiFrontal method + and direct sparse LU factorization. It is written in ANSI/ISO C, with a + MATLAB interface. UMFPACK relies on the Level-3 Basic + Linear Algebra Subprograms (dense matrix multiply) for its performance. + This code works on Windows and many versions of Unix (Sun Solaris, + Red Hat Linux, IBM AIX, SGI IRIX, and Compaq Alpha). +\end{abstract} +%------------------------------------------------------------------------------- + +Technical Report TR-04-003 (revised) + +UMFPACK Version 4.4 (Jan. 28, 2005), Copyright\copyright 2005 by Timothy A. +Davis. All Rights Reserved. + +{\bf UMFPACK License:} + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and ``Used by permission.'' + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +{\bf Availability:} + http://www.cise.ufl.edu/research/sparse/umfpack + +{\bf Acknowledgments:} + + This work was supported by the National Science Foundation, under + grants DMS-9504974, DMS-9803599, and CCR-0203270. + The upgrade to Version 4.1 and the inclusion of the + symmetric and 2-by-2 pivoting strategies + were done while the author was on sabbatical at + Stanford University and Lawrence Berkeley National Laboratory. + +%------------------------------------------------------------------------------- +\newpage +%------------------------------------------------------------------------------- + +\tableofcontents + +%------------------------------------------------------------------------------- +\newpage +\section{Overview} +%------------------------------------------------------------------------------- + +UMFPACK\footnote{Pronounced with two syllables: umph-pack} +Version 4.4 is a set of routines for solving systems of linear +equations, $\m{Ax}=\m{b}$, when $\m{A}$ is sparse and unsymmetric. It is based +on the Unsymmetric-pattern MultiFrontal method \cite{DavisDuff97,DavisDuff99}. +UMFPACK factorizes +$\m{PAQ}$, $\m{PRAQ}$, or $\m{PR}^{-1}\m{AQ}$ into the product $\m{LU}$, +where $\m{L}$ and $\m{U}$ +are lower and upper triangular, respectively, $\m{P}$ and $\m{Q}$ are +permutation matrices, and $\m{R}$ is a diagonal matrix of row scaling factors +(or $\m{R}=\m{I}$ if row-scaling is not used). Both $\m{P}$ and $\m{Q}$ are +chosen to reduce fill-in (new nonzeros in $\m{L}$ and $\m{U}$ that are not +present in $\m{A}$). The permutation $\m{P}$ has the dual role of reducing +fill-in and maintaining numerical accuracy (via relaxed partial pivoting +and row interchanges). + +The sparse matrix $\m{A}$ can be square or rectangular, singular +or non-singular, and real or complex (or any combination). Only square +matrices $\m{A}$ can be used to solve $\m{Ax}=\m{b}$ or related systems. +Rectangular matrices can only be factorized. + +UMFPACK first finds a column pre-ordering that reduces fill-in, without regard +to numerical values. It scales and analyzes the matrix, and then automatically +selects one of three strategies for pre-ordering the rows and columns: +{\em unsymmetric}, +{\em 2-by-2}, and +{\em symmetric}. These strategies are described below. + +First, all pivots with zero Markowitz cost are eliminated and placed in the +LU factors. The remaining submatrix $\m{S}$ is then analyzed. +The following rules are applied, and the first one that matches defines +the strategy. + +\begin{itemize} +\item Rule 1: $\m{A}$ rectangular $\implies$ unsymmetric. +\item Rule 2: + If the zero-Markowitz elimination results in a rectangular $\m{S}$, + or an $\m{S}$ whose diagonal has not been preserved, the + unsymmetric strategy is used. +\item The symmetry $\sigma_1$ of $\m{S}$ is computed. It is defined as + the number of {\em matched} off-diagonal entries, divided by the + total number of off-diagonal entries. An entry $s_{ij}$ is matched + if $s_{ji}$ is also an entry. They need not be numerically equal. + An {\em entry} is a value in $\m{A}$ which is present + in the input data structure. All nonzeros are entries, but some entries + may be numerically zero. + Rule 3: $\sigma_1 < 0.1 \implies$ unsymmetric. + The matrix is very unsymmetric. +\item Let $d$ be the number of nonzero entries on the diagonal of $\m{S}$. + Let $\m{S}$ be $\nu$-by-$\nu$. + Rule 4: $(\sigma_1 \ge 0.7) \:\wedge\: (d = \nu) \implies$ symmetric. + The matrix has a nearly symmetric nonzero pattern, and a zero-free + diagonal. +\end{itemize} + +If the strategy has not yet been determined, +the 2-by-2 strategy is attempted. A row permutation $\m{P}_2$ +is found which attempts to reduce the number of small +diagonal entries of $\m{P}_2 \m{S}$. +An entry $s_{ij}$ is determined to be small if +$|s_{ij}| < 0.01 \max |s_{*j}|$, or large otherwise. +If $s_{ii}$ is numerically small, the method attempts to swap +two rows $i$ and $j$, such that both $s_{ij}$ and $s_{ji}$ are large. +Once these rows are swapped, +they remain in place. Let $\sigma_2$ be the symmetry of $\m{P}_2 \m{S}$, +and let $d_2$ be the number of nonzero entries (either small or large) +on the diagonal of $\m{P}_2 \m{S}$. + +\begin{itemize} +\item Rule 5: + ($\sigma_2 > 1.1 \sigma_1) \:\wedge\: (d_2 > 0.9 \nu) \implies$ 2-by-2. + The 2-by-2 permutation has made the matrix significantly more symmetric. +\item Rule 6: $\sigma_2 < 0.7 \sigma_1 \implies$ unsymmetric. + The 2-by-2 strategy has significantly deteriorated the symmetry, +\item Rule 7: $\sigma_2 < 0.25 \implies$ unsymmetric. + The matrix is still very unsymmetric. +\item Rule 8: $\sigma_2 \ge 0.51 \implies$ 2-by-2. + The matrix is roughly symmetric. +\item Rule 9: $\sigma_2 \ge 0.999 \sigma_1 \implies$ 2-by-2. + The 2-by-2 permutation has preserved symmetry, or made it only + slightly worse. +\item Rule 10: if no rule has yet triggered, use the unsymmetric strategy. +\end{itemize} + +Each strategy is described below: +\begin{itemize} +\item {\em unsymmetric}: +The column pre-ordering of $\m{S}$ is computed by a modified version of COLAMD +\cite{DavisGilbertLarimoreNg00_algo,DavisGilbertLarimoreNg00,Larimore98}. +The method finds a symmetric permutation $\m{Q}$ of the matrix $\m{S}\tr\m{S}$ +(without forming $\m{S}\tr\m{S}$ explicitly). This is a good choice for +$\m{Q}$, since the Cholesky factors of $\m{(SQ)\tr(SQ)}$ are an upper bound (in +terms of nonzero pattern) of the factor $\m{U}$ for the unsymmetric LU +factorization ($\m{PSQ}=\m{LU}$) regardless of the choice of $\m{P}$ +\cite{GeorgeNg85,GeorgeNg87,GilbertNg93}. This modified version of +COLAMD also computes the column elimination tree and post-orders the +tree. It finds the upper bound on the number of nonzeros in L and U. +It also has a different threshold for determining dense rows and columns. +During factorization, the column pre-ordering can be modified. +Columns within a single super-column can be reshuffled, to reduce fill-in. +Threshold partial pivoting is used with no preference given to the diagonal +entry. Within a given pivot column $j$, an entry $a_{ij}$ can be chosen if +$|a_{ij}| \ge 0.1 \max |a_{*j}|$. Among those numerically acceptable +entries, the sparsest row $i$ is chosen as the pivot row. + +\item {\em 2-by-2}: +The symmetric strategy (see below) is applied to the matrix $\m{P}_2 \m{S}$, +rather than $\m{S}$. + +\item {\em symmetric}: +The column ordering is computed from AMD +\cite{AmestoyDavisDuff96,AmestoyDavisDuff03}, +applied to the pattern of $\m{S}+\m{S}\tr$ +followed by a post-ordering of the supernodal elimination +tree of $\m{S}+\m{S}\tr$. +No modification of the column pre-ordering is made during numerical +factorization. Threshold partial pivoting is used, with a strong +preference given to the diagonal entry. The diagonal entry is chosen if +$a_{jj} \ge 0.001 \max |a_{*j}|$. Otherwise, a sparse row is selected, +using the same method used by the unsymmetric strategy. + +\end{itemize} + +The symmetric and 2-by-2 strategies, and their automatic selection, +are new to Version 4.1. Version 4.0 only used the unsymmetric strategy. + +Once the strategy is selected, +the factorization of the matrix $\m{A}$ is broken down into the factorization +of a sequence of dense rectangular frontal matrices. The frontal matrices are +related to each other by a supernodal column elimination tree, in which each +node in the tree represents one frontal matrix. This analysis phase also +determines upper bounds on the memory usage, the floating-point operation count, +and the number of nonzeros in the LU factors. + +UMFPACK factorizes each {\em chain} of frontal matrices in a single working +array, similar to how the unifrontal method \cite{dusc:96} factorizes the whole +matrix. A chain of frontal matrices is a sequence of fronts where the parent +of front $i$ is $i$+1 in the supernodal column elimination tree. For the +nonsingular matrices factorized with the unsymmetric strategy, there are +exactly the same number of chains as there are leaves in the supernodal +column elimination tree. UMFPACK is an +outer-product based, right-looking method. At the $k$-th step of Gaussian +elimination, it represents the updated submatrix $\m{A}_k$ as an implicit +summation of a set of dense sub-matrices (referred to as {\em elements}, +borrowing a phrase from finite-element methods) that arise when the frontal +matrices are factorized and their pivot rows and columns eliminated. + +Each frontal matrix represents the elimination of one or more columns; +each column of $\m{A}$ will be eliminated in a specific frontal matrix, +and which frontal matrix will be used for which column is determined by +the pre-analysis phase. The pre-analysis phase also determines the worst-case +size of each frontal matrix so that they can hold any candidate pivot column +and any candidate pivot row. From the perspective of the analysis phase, any +candidate pivot column in the frontal matrix is identical (in terms of nonzero +pattern), and so is any row. However, the numeric factorization phase has +more information than the analysis phase. It uses this information to reorder +the columns within each frontal matrix to reduce fill-in. Similarly, since +the number of nonzeros in each row and column are maintained (more precisely, +COLMMD-style approximate degrees \cite{GilbertMolerSchreiber}), a pivot row can +be selected based on sparsity-preserving criteria (low degree) as well as +numerical considerations (relaxed threshold partial pivoting). + +When the symmetric or 2-by-2 strategies are used, +the column preordering is not refined during numeric factorization. +Row pivoting for sparsity and numerical accuracy is performed if the +diagonal entry is too small. + +More details of the method, including experimental results, are +described in \cite{Davis03,Davis03_algo}, available at +http://www.cise.ufl.edu/tech-reports. + +%------------------------------------------------------------------------------- +\section{Availability} +%------------------------------------------------------------------------------- + +In addition to appearing as a Collected Algorithm of the ACM, +UMFPACK Version 4.4 is available at http://www.cise.ufl.edu/research/sparse. +Version 4.3 is included as a built-in routine in MATLAB +7.1. Version 4.0 (in MATLAB 6.5) +does not have the symmetric or 2-by-2 strategies and it takes +less advantage of the level-3 +BLAS \cite{DaydeDuff99,ACM679a,ATLAS,GotoVandeGeijn02}. +Version 4.4 (and v4.3 through v4.1) tend to be much faster than Version 4.0, +particularly on unsymmetric matrices with mostly symmetric +nonzero pattern (such as finite element and circuit simulation matrices). +Version 3.0 and following make +use of a modified version of COLAMD V2.0 by Timothy A.~Davis, Stefan +Larimore, John Gilbert, and Esmond Ng. The original COLAMD V2.1 is available in +as a built-in routine in MATLAB V6.0 (or later), and at +http://www.cise.ufl.edu/research/sparse. +These codes are also available in Netlib \cite{netlib} at +http://www.netlib.org. +UMFPACK Versions 2.2.1 and earlier, co-authored with Iain Duff, +are available at http://www.cise.ufl.edu/research/sparse and as +MA38 (functionally equivalent to Version 2.2.1) in the Harwell +Subroutine Library. + +%------------------------------------------------------------------------------- +\section{Primary changes from prior versions} +%------------------------------------------------------------------------------- + +A detailed list of changes is in the {\tt ChangeLog} file. + +%------------------------------------------------------------------------------- +\subsection{Version 4.4} +%------------------------------------------------------------------------------- + +Bug fix in strategy selection in {\tt umfpack\_*\_qsymbolic}. +Added packed complex case for all complex input/output arguments. +Added {\tt umfpack\_get\_determinant}. +Added minimal support for Microsoft Visual Studio +(the {\tt umf\_multicompile.c} file). + +%------------------------------------------------------------------------------- +\subsection{Version 4.3.1} +%------------------------------------------------------------------------------- + +Minor bug fix in the forward/backsolve. This bug had the effect of turning +off iterative refinement when solving $\m{A}\tr\m{x}=\m{b}$ after factorizing +$\m{A}$. UMFPACK mexFunction now factorizes $\m{A}\tr$ in its forward-slash +operation. + +%------------------------------------------------------------------------------- +\subsection{Version 4.3} +%------------------------------------------------------------------------------- + +No changes are visible to the C or MATLAB user, except the presence of +one new control parameter in the {\tt Control} array, +and three new statistics in the {\tt Info} array. +The primary change is the addition of an (optional) drop tolerance. + +%------------------------------------------------------------------------------- +\subsection{Version 4.1} +%------------------------------------------------------------------------------- + +The following is a summary of the main changes that are visible to the C +or MATLAB user: + +\begin{enumerate} + +\item New ordering strategies added. No changes are required in user code + (either C or MATLAB) to use the new default strategy, which is an automatic + selection of the unsymmetric, symmetric, or 2-by-2 strategies. + +\item Row scaling added. This is only visible to the MATLAB caller when using + the form {\tt [L,U,P,Q,R] = umfpack (A)}, to retrieve the LU factors. + Likewise, it is only visible to the C caller when the LU factors are + retrieved, or when solving systems with just $\m{L}$ or $\m{U}$. + New C-callable and MATLAB-callable routines are included to get and to + apply the scale factors computed by UMFPACK. Row scaling is enabled by + default, but can be disabled. Row scaling usually leads to a better + factorization, particularly when the symmetric strategy is used. + +\item Error code {\tt UMFPACK\_ERROR\_problem\_to\_large} removed. + Version 4.0 would generate this error when the upper bound memory usage + exceeded 2GB (for the {\tt int} version), even when the actual memory + usage was less than this. The new version properly handles this case, + and can successfully factorize the matrix if sufficient memory is + available. + +\item New control parameters and statistics provided. + +\item The AMD symmetric approximate minimum degree ordering routine added + \cite{AmestoyDavisDuff96,AmestoyDavisDuff03}. + It is used by UMFPACK, and can also be called independently from C or + MATLAB. + +\item The {\tt umfpack} mexFunction now returns permutation matrices, not + permutation vectors, when using the form {\tt [L,U,P,Q] = umfpack (A)} + or the new form {\tt [L,U,P,Q,R] = umfpack (A)}. + +\item New arguments added to the user-callable routines + {\tt umfpack\_*\_symbolic}, + {\tt umfpack\_*\_qsymbolic}, + {\tt umfpack\_*\_get\_numeric}, and + {\tt umfpack\_*\_get\_symbolic}. + The symbolic analysis now makes use of the numerical values of the matrix + $\m{A}$, to guide the 2-by-2 strategy. The subsequent matrix passed to + the numeric factorization step does not have to have the same numerical + values. All of the new arguments are optional. If you do not wish to + include them, simply pass {\tt NULL} pointers instead. The 2-by-2 strategy + will assume all entries are numerically large, for example. + +\item New routines added to save and load the {\tt Numeric} and {\tt Symbolic} + objects to and from a binary file. + +\item A Fortran interface added. It provides access to a subset of + UMFPACK's features. + +\item You can compute an incomplete LU factorization, by dropping small + entries from $\m{L}$ and $\m{U}$. By default, no nonzero entry is + dropped, no matter how small in absolute value. This feature is new + to Version 4.3. + +\end{enumerate} + +%------------------------------------------------------------------------------- +\section{Using UMFPACK in MATLAB} +%------------------------------------------------------------------------------- + +The easiest way to use UMFPACK is within MATLAB. Version 4.3 is a built-in +routine in MATLAB 7.1, and is used in {\tt x = A}$\backslash${\tt b} when +{\tt A} is sparse, square, unsymmetric (or symmetric but not positive definite), +and with nonzero entries that are not confined in a narrow band. +It is also used for the {\tt [L,U,P,Q] = lu (A)} usage of {\tt lu}. +Type {\tt help lu} in MATLAB 6.5 or later for more details. + +To use the UMFPACK mexFunction, you must download and compile it, +since the mexFunction itself is not part of MATLAB. +The following discussion assumes that +you have MATLAB Version 6.0 or later (which includes the BLAS, and the +{\tt colamd} ordering routine). To compile both the UMFPACK and AMD +mexFunctions, just type {\tt make} in the Unix system shell, +while in the {\tt UMFPACK} directory. +You can also type {\tt umfpack\_make} in MATLAB, if you are in the +{\tt UMFPACK/MATLAB} directory, or if that directory is in your MATLAB path. +This works on any system with MATLAB, including Windows. +See Section~\ref{Install} for more details on how to install UMFPACK. +Once installed, the UMFPACK mexFunction can analyze, factor, and solve linear +systems. Table~\ref{matlab} summarizes some of the more common uses +of the UMFPACK mexFunction within MATLAB. + +An optional input argument can be used to modify the control parameters for +UMFPACK, and an optional output argument provides statistics on the +factorization. + +Refer to the AMD User Guide for more details about the AMD mexFunction. + +\begin{table} +\caption{Using UMFPACK's MATLAB interface} +\label{matlab} +\vspace{0.1in} +{\footnotesize +\begin{tabular}{l|l|l} +\hline +Function & Using UMFPACK & MATLAB 6.0 equivalent \\ +\hline + & & \\ +\begin{minipage}[t]{1.5in} +Solve $\m{Ax}=\m{b}$. +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +x = umfpack (A,'\',b) ; +\end{verbatim} +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +x = A \ b ; +\end{verbatim} +\end{minipage} + \\ + & & \\ +\hline + & & \\ +\begin{minipage}[t]{1.5in} +Solve $\m{Ax}=\m{b}$ using a different row and column pre-ordering +(symmetric ordering). +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +S = spones (A) ; +Q = symamd (S+S') ; +Control = umfpack ; +Control (6) = 3 ; +x = umfpack (A,Q,'\',b,Control) ; +\end{verbatim} +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +spparms ('autommd',0) ; +S = spones (A) ; +Q = symamd (S+S') ; +x = A (Q,Q) \ b (Q) ; +x (Q) = x ; +spparms ('autommd',1) ; +\end{verbatim} +\end{minipage} + \\ + & & \\ +\hline + & & \\ +\begin{minipage}[t]{1.5in} +Solve $\m{A}\tr\m{x}\tr = \m{b}\tr$. +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +x = umfpack (b,'/',A) ; +\end{verbatim} +Note: $\m{A}$ is factorized. +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +x = b / A ; +\end{verbatim} +Note: $\m{A}\tr$ is factorized. +\end{minipage} + \\ + & & \\ +\hline + & & \\ +\begin{minipage}[t]{1.5in} +Scale and factorize $\m{A}$, then solve $\m{Ax}=\m{b}$. +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +[L,U,P,Q,R] = umfpack (A) ; +c = P * (R \ b) ; +x = Q * (U \ (L \ c)) ; +\end{verbatim} +\end{minipage} +& +\begin{minipage}[t]{2.2in} +\begin{verbatim} +[m n] = size (A) ; +r = full (sum (abs (A), 2)) ; +r (find (r == 0)) = 1 ; +R = spdiags (r, 0, m, m) ; +I = speye (n) ; +Q = I (:, colamd (A)) ; +[L,U,P] = lu ((R\A)*Q) ; +c = P * (R \ b) ; +x = Q * (U \ (L \ c)) ; +\end{verbatim} +\end{minipage} + \\ + & & \\ +\hline +\end{tabular} +} +\end{table} + +Note: in MATLAB 6.5 or later, use {\tt spparms ('autoamd',0)} in addition to +{\tt spparms ('autommd',0)}, in Table~\ref{matlab}, to turn off MATLAB's +default reordering. + +UMFPACK requires +{\tt b} to be a dense vector (real or complex) of the appropriate dimension. +This is more restrictive than what you can do with MATLAB's +backslash or forward slash. See {\tt umfpack\_solve} for an M-file that +removes this restriction. +This restriction does not apply to the built-in backslash operator +in MATLAB 6.5 or later, which uses UMFPACK to factorize the matrix. +You can do this yourself in MATLAB: + +{\footnotesize +\begin{verbatim} + [L,U,P,Q,R] = umfpack (A) ; + x = Q * (U \ (L \ (P * (R \ b)))) ; +\end{verbatim} +} + +or, with no row scaling: + +{\footnotesize +\begin{verbatim} + [L,U,P,Q] = umfpack (A) ; + x = Q * (U \ (L \ (P * b))) ; +\end{verbatim} +} + +The above examples do not make use of the iterative refinement +that is built into +{\tt x = }{\tt umfpack (A,'}$\backslash${\tt ',b)} +however. + +MATLAB's {\tt [L,U,P] = lu(A)} returns a lower triangular {\tt L}, an upper +triangular {\tt U}, and a permutation matrix {\tt P} such that {\tt P*A} is +equal to {\tt L*U}. UMFPACK behaves differently. By default, it scales +the rows of {\tt A} and reorders the columns of {\tt A} prior to +factorization, so that {\tt L*U} is equal to {\tt P*(R}$\backslash${\tt A)*Q}, +where {\tt R} is a diagonal sparse matrix of scale factors for the rows +of {\tt A}. The scale factors {\tt R} are applied to {\tt A} via the MATLAB +expression {\tt R}$\backslash${\tt A} to avoid multiplying by +the reciprocal, which can be numerically inaccurate. + +There are more options; you can provide your own column pre-ordering (in which +case UMFPACK does not call COLAMD or AMD), you can modify other control settings +(similar to the {\tt spparms} in MATLAB), and you can get various statistics on +the analysis, factorization, and solution of the linear system. Type +{\tt umfpack\_details} and {\tt umfpack\_report} in MATLAB for more +information. Two demo M-files are provided. Just type {\tt umfpack\_simple} +and {\tt umfpack\_demo} to run them. +The output of these two programs should be about the same +as the files {\tt umfpack\_simple.m.out} and {\tt umfpack\_demo.m.out} +that are provided. + +Factorizing {\tt A'} (or {\tt A.'}) and using the transposed factors can +sometimes be faster than factorizing {\tt A}. It can also be preferable to +factorize {\tt A'} if {\tt A} is rectangular. UMFPACK pre-orders the columns +to maintain sparsity; the row ordering is not determined until the matrix +is factorized. Thus, if {\tt A} is {\tt m} by {\tt n} with rank {\tt m} +and {\tt m} $<$ {\tt n}, then {\tt umfpack} might not find a factor +{\tt U} with a zero-free diagonal. Unless the matrix ill-conditioned or +poorly scaled, factorizing {\tt A'} in this case will guarantee that both +factors will have zero-free diagonals. Here's how you can factorize {\tt A'} +and get the factors of {\tt A} instead: + +\begin{verbatim} + [l,u,p,q] = umfpack (A') ; + L = u' ; + U = l' ; + P = q ; + Q = p ; + clear l u p q +\end{verbatim} + +This is an alternative to {\tt [L,U,P,Q]=umfpack(A)}. + +A simple M-file ({\tt umfpack\_btf}) is provided that first permutes the matrix +to upper block triangular form, using MATLAB's {\tt dmperm} routine, and then +solves each block. The LU factors are not returned. Its usage is simple: +{\tt x = umfpack\_btf(A,b)}. Type {\tt help umfpack\_btf} for more options. +An estimate of the 1-norm of {\tt L*U-P*A*Q} can be computed in MATLAB +as {\tt lu\_normest(P*A*Q,L,U)}, using the {\tt lu\_normest.m} M-file +by Hager and Davis \cite{DavisHager99} that is included with the +UMFPACK distribution. With row scaling enabled, use +{\tt lu\_normest(P*(R}$\backslash${\tt A)*Q,L,U)} instead. + +One issue you may encounter is how UMFPACK allocates its memory when being used +in a mexFunction. One part of its working space is of variable size. The +symbolic analysis phase determines an upper bound on the size of this memory, +but not all of this memory will typically be used in the numerical +factorization. UMFPACK tries to allocate a decent amount of working space. +This is 70\% of the upper bound, by default, for the unsymmetric strategy. +For the symmetric strategy, the fraction of the upper bound is computed +automatically (assuming a best-case scenario with no numerical pivoting +required during numeric factorization). +If this initial allocation fails, it reduces its request +and uses less memory. If the space is not large enough during factorization, +it is increased via {\tt mxRealloc}. + +However, {\tt mxMalloc} and {\tt mxRealloc} abort the {\tt umfpack} mexFunction +if they fail, so this strategy does not work in MATLAB. The strategy works fine +when {\tt malloc} or the internal memory allocator {\tt utMalloc} are used +instead, since those routines return {\tt NULL} on failure, and do not terminate +the mexFunction. The {\tt umfpack} mexFunction can be compiled to use +{\tt utMalloc}, but this is an internal undocumented utility routine in MATLAB, +and thus using {\tt utMalloc} might not always be successful. +To use the documented {\tt mxMalloc} routine instead, compile the +mexFunction with the {\tt -DNUTIL} flag enabled. + +To compute the determinant with UMFPACK: + +\begin{verbatim} + d = umfpack (A, 'det') ; + [d e] = umfpack (A, 'det') ; +\end{verbatim} + +The first case is identical to MATLAB's {\tt det}. +The second case returns the determinant in the form +$d \times 10^e$, which avoids overflow if $e$ is large. + +%------------------------------------------------------------------------------- +\section{Using UMFPACK in a C program} +\label{C} +%------------------------------------------------------------------------------- + +The C-callable UMFPACK library consists of 32 user-callable routines and one +include file. All but three of the routines come in four versions, with +different sizes of integers and for real or complex floating-point numbers: +\begin{enumerate} +\item {\tt umfpack\_di\_*}: real double precision, {\tt int} integers. +\item {\tt umfpack\_dl\_*}: real double precision, {\tt long} integers. +\item {\tt umfpack\_zi\_*}: complex double precision, {\tt int} integers. +\item {\tt umfpack\_zl\_*}: complex double precision, {\tt long} integers. +\end{enumerate} +where {\tt *} denotes the specific name of one of the routines. +Routine names beginning with {\tt umf\_} are internal to the package, +and should not be called by the user. The include file {\tt umfpack.h} +must be included in any C program that uses UMFPACK. +The other three routines are the same for all four versions. + +In addition, the C-callable AMD library distributed with UMFPACK +includes 4 user-callable routines (in two versions with {\tt int} and +{\tt long} integers) and one include file. Refer to the AMD documentation +for more details. + +Use only one version for any one problem; do not attempt to use one version +to analyze the matrix and another version to factorize the matrix, for example. + +The notation {\tt umfpack\_di\_*} refers to all user-callable routines +for the real double precision and {\tt int} integer case. The notation +{\tt umfpack\_*\_numeric}, for example, refers all four versions +(real/complex, int/long) of a single operation +(in this case numeric factorization). + +%------------------------------------------------------------------------------- +\subsection{The size of an integer} +%------------------------------------------------------------------------------- + +The {\tt umfpack\_di\_*} and {\tt umfpack\_zi\_*} routines use {\tt int} integer +arguments; those starting with {\tt umfpack\_dl\_} or {\tt umfpack\_zl\_} +use {\tt long} integer arguments. If you compile UMFPACK in the standard +ILP32 mode (32-bit {\tt int}'s, {\tt long}'s, and pointers) then the versions +are essentially identical. You will be able to solve problems using up to 2GB +of memory. If you compile UMFPACK in the standard LP64 mode, the size of an +{\tt int} remains 32-bits, but the size of a {\tt long} and a pointer both get +promoted to 64-bits. In the LP64 mode, the {\tt umfpack\_dl\_*} +and {\tt umfpack\_zl\_*} routines can solve huge +problems (not limited to 2GB), limited of course by the amount of available +memory. The only drawback to the 64-bit mode is that not all BLAS libraries +support 64-bit integers. This limits the performance you will obtain. +Those that do support 64-bit integers are specific to particular +architectures, and are not portable. UMFPACK and AMD should be compiled +in the same mode. +If you compile UMFPACK and AMD in the LP64 mode, +be sure to add {\tt -DLP64} to the compilation command. See the examples in +{\tt Make.alpha}, {\tt Make.sgi}, and {\tt Make.solaris}. + +%------------------------------------------------------------------------------- +\subsection{Real and complex floating-point} +%------------------------------------------------------------------------------- + +The {\tt umfpack\_di\_*} and {\tt umfpack\_dl\_*} routines take (real) double +precision arguments, and return double precision arguments. In the +{\tt umfpack\_zi\_*} and {\tt umfpack\_zl\_*} routines, these same arguments +hold the real part of the matrices; and second double precision arrays hold +the imaginary part of the input and output matrices. Internally, complex +numbers are stored in arrays with their real and imaginary parts interleaved, +as required by the BLAS (``packed'' complex form). + +New to Version 4.4 is the option of providing input/output arguments +in packed complex form. + +%------------------------------------------------------------------------------- +\subsection{Primary routines, and a simple example} +%------------------------------------------------------------------------------- + +Five primary UMFPACK routines are required to factorize $\m{A}$ or +solve $\m{Ax}=\m{b}$. They are fully described in Section~\ref{Primary}: + +\begin{itemize} +\item {\tt umfpack\_*\_symbolic}: + + Pre-orders the columns of $\m{A}$ to reduce fill-in. + Returns an opaque {\tt Symbolic} object as a {\tt void *} + pointer. The object contains the symbolic analysis and is needed for the + numeric factorization. This routine requires only $O(|\m{A}|)$ space, + where $|\m{A}|$ is the number of nonzero entries in the matrix. It computes + upper bounds on the nonzeros in $\m{L}$ and $\m{U}$, the floating-point + operations required, and the memory usage of {\tt umfpack\_*\_numeric}. The + {\tt Symbolic} object is small; it contains just the column pre-ordering, + the supernodal column elimination tree, and information about each frontal + matrix. It is no larger than about $13n$ integers if $\m{A}$ is + $n$-by-$n$. + +\item {\tt umfpack\_*\_numeric}: + + Numerically scales and then factorizes a sparse matrix into + $\m{PAQ}$, $\m{PRAQ}$, or $\m{PR}^{-1}\m{AQ}$ into the product $\m{LU}$, + where + $\m{P}$ and $\m{Q}$ are permutation matrices, $\m{R}$ is a diagonal + matrix of scale factors, $\m{L}$ is lower triangular with unit diagonal, + and $\m{U}$ is upper triangular. Requires the + symbolic ordering and analysis computed by {\tt umfpack\_*\_symbolic} + or {\tt umfpack\_*\_qsymbolic}. + Returns an opaque {\tt Numeric} object as a + {\tt void *} pointer. The object contains the numerical factorization and + is used by {\tt umfpack\_*\_solve}. You can factorize a new matrix with a + different values (but identical pattern) as the matrix analyzed by + {\tt umfpack\_*\_symbolic} or {\tt umfpack\_*\_qsymbolic} by re-using the + {\tt Symbolic} object (this feature is available when using UMFPACK in a + C or Fortran program, but not in MATLAB). + The matrix + $\m{U}$ will have zeros on the diagonal if $\m{A}$ is singular; this + produces a warning, but the factorization is still valid. + +\item {\tt umfpack\_*\_solve}: + + Solves a sparse linear system ($\m{Ax}=\m{b}$, $\m{A}\tr\m{x}=\m{b}$, or + systems involving just $\m{L}$ or $\m{U}$), using the numeric factorization + computed by {\tt umfpack\_*\_numeric}. Iterative refinement with sparse + backward error \cite{ardd:89} is used by default. The matrix $\m{A}$ must + be square. If it is singular, then a divide-by-zero will occur, and your + solution with contain IEEE Inf's or NaN's in the appropriate places. + +\item {\tt umfpack\_*\_free\_symbolic}: + + Frees the {\tt Symbolic} object created by {\tt umfpack\_*\_symbolic} + or {\tt umfpack\_*\_qsymbolic}. + +\item {\tt umfpack\_*\_free\_numeric}: + + Frees the {\tt Numeric} object created by {\tt umfpack\_*\_numeric}. + +\end{itemize} + +Be careful not to free a {\tt Symbolic} object with +{\tt umfpack\_*\_free\_numeric}. Nor should you attempt to free a {\tt Numeric} +object with {\tt umfpack\_*\_free\_symbolic}. +Failure to free these objects will lead to memory leaks. + +The matrix $\m{A}$ is represented in compressed column form, which is +identical to the sparse matrix representation used by MATLAB. It consists +of three or four arrays, where the matrix is {\tt m}-by-{\tt n}, +with {\tt nz} entries. For the {\tt int} version of UMFPACK: + +{\footnotesize +\begin{verbatim} + int Ap [n+1] ; + int Ai [nz] ; + double Ax [nz] ; +\end{verbatim} +} + +For the {\tt long} version of UMFPACK: + +{\footnotesize +\begin{verbatim} + long Ap [n+1] ; + long Ai [nz] ; + double Ax [nz] ; +\end{verbatim} +} + +The complex versions add another array for the imaginary part: + +{\footnotesize +\begin{verbatim} + double Az [nz] ; +\end{verbatim} +} + +Alternatively, if {\tt Az} is {\tt NULL}, +the real part of the $k$th entry is located in +{\tt Ax[2*k]} and the imaginary part is located in +{\tt Ax[2*k+1]}, and the {\tt Ax} array is of size {\tt 2*nz}. + +All nonzeros are entries, but an entry may be numerically zero. The row indices +of entries in column {\tt j} are stored in + {\tt Ai[Ap[j]} \ldots {\tt Ap[j+1]-1]}. +The corresponding numerical values are stored in + {\tt Ax[Ap[j]} \ldots {\tt Ap[j+1]-1]}. +The imaginary part, for the complex versions, is stored in + {\tt Az[Ap[j]} \ldots {\tt Ap[j+1]-1]} + (see above for the packed complex case). + +No duplicate row indices may be present, and the row indices in any given +column must be sorted in ascending order. The first entry {\tt Ap[0]} must be +zero. The total number of entries in the matrix is thus {\tt nz = Ap[n]}. +Except for the fact that extra zero entries can be included, there is thus a +unique compressed column representation of any given matrix $\m{A}$. +For a more flexible method for providing an input matrix to UMFPACK, +see Section~\ref{triplet}. + +Here is a simple main program, {\tt umfpack\_simple.c}, that illustrates the +basic usage of UMFPACK. See Section~\ref{Synopsis} for a short description +of each calling sequence, including a list of options for the first +argument of {\tt umfpack\_di\_solve}. + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_simple.c via sed +\end{verbatim} +} + +The {\tt Ap}, {\tt Ai}, and {\tt Ax} arrays represent the matrix +\[ +\m{A} = \left[ +\begin{array}{rrrrr} + 2 & 3 & 0 & 0 & 0 \\ + 3 & 0 & 4 & 0 & 6 \\ + 0 & -1 & -3 & 2 & 0 \\ + 0 & 0 & 1 & 0 & 0 \\ + 0 & 4 & 2 & 0 & 1 \\ +\end{array} +\right]. +\] +and the solution to $\m{Ax}=\m{b}$ is $\m{x} = [1 \, 2 \, 3 \, 4 \, 5]\tr$. +The program uses default control settings and does not return any statistics +about the ordering, factorization, or solution ({\tt Control} and {\tt Info} +are both {\tt (double *) NULL}). It also ignores the status value returned by +most user-callable UMFPACK routines. + +%------------------------------------------------------------------------------- +\subsection{A note about zero-sized arrays} +%------------------------------------------------------------------------------- + +UMFPACK uses many user-provided arrays of +size {\tt m} or {\tt n} (the order of the matrix), and of size +{\tt nz} (the number of nonzeros in a matrix). UMFPACK does not handle +zero-dimensioned arrays; +it returns an error code if {\tt m} or {\tt n} +are zero. However, {\tt nz} can be zero, since all singular matrices are +handled correctly. If you attempt to {\tt malloc} an array of size {\tt nz} += 0, however, {\tt malloc} will return a null pointer which UMFPACK will report +as a missing argument. If you {\tt malloc} an array of +size {\tt nz} to pass to UMFPACK, make sure that you handle the {\tt nz} = 0 +case correctly (use a size equal to the maximum of {\tt nz} and 1, or use a +size of {\tt nz+1}). + +%------------------------------------------------------------------------------- +\subsection{Alternative routines} +%------------------------------------------------------------------------------- + +Three alternative routines are provided that modify UMFPACK's default +behavior. They are fully described in Section~\ref{Alternative}: + +\begin{itemize} +\item {\tt umfpack\_*\_defaults}: + + Sets the default control parameters in the {\tt Control} array. These can + then be modified as desired before passing the array to the other UMFPACK + routines. Control parameters are summarized in Section~\ref{control_param}. + Three particular parameters deserve special notice. + UMFPACK uses relaxed partial pivoting, where a candidate pivot entry is + numerically acceptable if its magnitude is greater than or equal to a + tolerance parameter times the magnitude of the largest entry in the same + column. The parameter {\tt Control [UMFPACK\_PIVOT\_TOLERANCE]} has a + default value of 0.1, and is used for the unsymmetric strategy. + For complex matrices, a cheap approximation of the absolute value is + used for the threshold pivoting test + ($|a| \approx |a_{\mbox{real}}|+|a_{\mbox{imag}}|$). + + For the symmetric strategy, a second tolerance is used for diagonal + entries: \newline {\tt Control [UMFPACK\_SYM\_PIVOT\_TOLERANCE]}, with + a default value of 0.001. The first parameter (with a default of 0.1) + is used for any off-diagonal candidate pivot entries. + + These two parameters may be too small for some matrices, particularly for + ill-conditioned or poorly scaled ones. With the default pivot tolerances + and default iterative refinement, + {\tt x = umfpack (A,'}$\backslash${\tt ',b)} + is just as accurate as (or more accurate) than + {\tt x = A}$\backslash${\tt b} + in MATLAB 6.1 for nearly all matrices. + + If {\tt Control [UMFPACK\_PIVOT\_TOLERANCE]} is zero, than any + nonzero entry is acceptable as a pivot (this is changed from Version 4.0, + which treated a value of 0.0 the same as 1.0). If the symmetric strategy is + used, and {\tt Control [UMFPACK\_SYM\_PIVOT\_TOLERANCE]} is zero, then any + nonzero entry on the diagonal is accepted as a pivot. Off-diagonal pivoting + will still occur if the diagonal entry is exactly zero. The + {\tt Control [UMFPACK\_SYM\_PIVOT\_TOLERANCE]} parameter is new to Version + 4.1. It is similar in function to the pivot tolerance for left-looking + methods (the MATLAB {\tt THRESH} option in {\tt [L,U,P] = lu (A, THRESH)}, + and the pivot tolerance parameter in SuperLU). + + The parameter {\tt Control [UMFPACK\_STRATEGY]} can be used to bypass + UMFPACK's automatic strategy selection. The automatic strategy nearly + always selects the best method. When it does not, the different methods + nearly always give about the same quality of results. There may be + cases where the automatic strategy fails to pick a good strategy. Also, + you can save some computing time if you know the right strategy for your + set of matrix problems. + +\item {\tt umfpack\_*\_qsymbolic}: + + An alternative to {\tt umfpack\_*\_symbolic}. Allows the user to specify + his or her own column pre-ordering, rather than using the default COLAMD + or AMD pre-orderings. For example, a graph partitioning-based order + of $\m{A}\tr\m{A}$ would be suitable for UMFPACK's unsymmetric strategy. + A partitioning of $\m{A}+\m{A}\tr$ would be suitable for UMFPACK's + symmetric or 2-by-2 strategies. + +\item {\tt umfpack\_*\_wsolve}: + + An alternative to {\tt umfpack\_*\_solve} which does not dynamically + allocate any memory. Requires the user to pass two additional work + arrays. + +\end{itemize} + +%------------------------------------------------------------------------------- +\subsection{Matrix manipulation routines} +\label{triplet} +%------------------------------------------------------------------------------- + +The compressed column data structure is compact, and simplifies the UMFPACK +routines that operate on the sparse matrix $\m{A}$. However, it can be +inconvenient for the user to generate. Section~\ref{Manipulate} presents the +details of routines for manipulating sparse matrices in {\em triplet} form, +compressed column form, and compressed row form (the transpose of the +compressed column form). The triplet form of a matrix consists of three or +four arrays. For the {\tt int} version of UMFPACK: + +{\footnotesize +\begin{verbatim} + int Ti [nz] ; + int Tj [nz] ; + double Tx [nz] ; +\end{verbatim} +} + +For the {\tt long} version: + +{\footnotesize +\begin{verbatim} + long Ti [nz] ; + long Tj [nz] ; + double Tx [nz] ; +\end{verbatim} +} + +The complex versions use another array to hold the imaginary part: + +{\footnotesize +\begin{verbatim} + double Tz [nz] ; +\end{verbatim} +} + +The {\tt k}-th triplet is $(i,j,a_{ij})$, where $i =$ {\tt Ti[k]}, +$j =$ {\tt Tj[k]}, and $a_{ij} =$ {\tt Tx[k]}. For the complex versions, +{\tt Tx[k]} is the real part of $a_{ij}$ and +{\tt Tz[k]} is the imaginary part. +The triplets can be in any +order in the {\tt Ti}, {\tt Tj}, and {\tt Tx} arrays (and {\tt Tz} for +the complex versions), and duplicate entries may +exist. +If {\tt Tz} is NULL, then the array {\tt Tx} becomes of size {\tt 2*nz}, +and the real and imaginary parts of the +{\tt k}-th triplet are located in {\tt Tx[2*k]} and {\tt Tx[2*k+1]}, +respectively. +Any duplicate entries are summed when the triplet form is converted to +compressed column form. This is a convenient way to create a matrix arising in +finite-element methods, for example. + +Four routines are provided for manipulating sparse matrices: + +\begin{itemize} +\item {\tt umfpack\_*\_triplet\_to\_col}: + + Converts a triplet form of a matrix to compressed column form (ready for + input to \newline + {\tt umfpack\_*\_symbolic}, {\tt umfpack\_*\_qsymbolic}, and + {\tt umfpack\_*\_numeric}). Identical to {\tt A = spconvert(i,j,x)} in + MATLAB, except that zero entries are not removed, so that the pattern of + entries in the compressed column form of $\m{A}$ are fully under user + control. This is important if you want to factorize a new matrix with the + {\tt Symbolic} object from a prior matrix with the same pattern as the new + one. + +\item {\tt umfpack\_*\_col\_to\_triplet}: + + The opposite of {\tt umfpack\_*\_triplet\_to\_col}. Identical to + {\tt [i,j,x] = find(A)} in MATLAB, except that numerically zero entries + may be included. + +\item {\tt umfpack\_*\_transpose}: + + Transposes and optionally permutes a column form matrix \cite{Gustavson78}. + Identical to + {\tt R = A(P,Q)'} (linear algebraic transpose, using the complex conjugate) + or {\tt R = A(P,Q).'} (the array transpose) + in MATLAB, except for the presence of numerically zero entries. + + Factorizing $\m{A}\tr$ and then solving $\m{Ax}=\m{b}$ with the transposed + factors can sometimes be much faster or much slower than factorizing + $\m{A}$. It is highly dependent on your particular matrix. + +\item {\tt umfpack\_*\_scale}: + + Applies the row scale factors to a user-provided vector. This is not + required to solve the sparse linear system $\m{Ax}=\m{b}$ or + $\m{A}\tr\m{x}=\m{b}$, since {\tt umfpack\_*\_solve} applies the scale + factors for those systems. + +\end{itemize} + +It is quite easy to add matrices in triplet form, subtract them, transpose +them, permute them, construct a submatrix, and multiply a triplet-form matrix +times a vector. UMFPACK does not provide code for these basic operations, +however. Refer to the discussion of +{\tt umfpack\_*\_triplet\_to\_col} in Section~\ref{Manipulate} for more details +on how to compute these operations in your own code. +The only primary matrix operation not provided by UMFPACK is the +multiplication of two sparse matrices \cite{Gustavson78}. +A future package under development (as of Jan. 2005), CHOLMOD, +will provide many of these matrix operations, which +can then be used in conjunction with UMFPACK. +Watch my web page for details. + +%------------------------------------------------------------------------------- +\subsection{Getting the contents of opaque objects} +%------------------------------------------------------------------------------- + +There are cases where you may wish to do more with the LU factorization +of a matrix than solve a linear system. The opaque {\tt Symbolic} and +{\tt Numeric} objects are just that - opaque. You cannot do anything with them +except to pass them back to subsequent calls to UMFPACK. Three routines +are provided for copying their contents into user-provided arrays using simpler +data structures. Four routines are provided for saving and loading the +{\tt Numeric} and {\tt Symbolic} objects to/from binary files. +An additional routine is provided that computes the determinant. +They are fully described in Section~\ref{Get}: + +\begin{itemize} +\item {\tt umfpack\_*\_get\_lunz}: + + Returns the number of nonzeros in $\m{L}$ and $\m{U}$. + +\item {\tt umfpack\_*\_get\_numeric}: + + Copies $\m{L}$, $\m{U}$, $\m{P}$, $\m{Q}$, and $\m{R}$ + from the {\tt Numeric} object + into arrays provided by the user. The matrix $\m{L}$ is returned in + compressed row form (with the column indices in each row sorted in ascending + order). The matrix $\m{U}$ is returned in compressed column form (with + sorted columns). There are no explicit zero entries in $\m{L}$ and $\m{U}$, + but such entries may exist in the {\tt Numeric} object. The permutations + $\m{P}$ and $\m{Q}$ are represented as permutation vectors, where + {\tt P[k] = i} means that row {\tt i} of the original matrix is the + the {\tt k}-th row of $\m{PAQ}$, and where + {\tt Q[k] = j} means that column {\tt j} of the original matrix is the + {\tt k}-th column of $\m{PAQ}$. This is identical to how MATLAB uses + permutation vectors (type {\tt help colamd} in MATLAB 6.1 or later). + +\item {\tt umfpack\_*\_get\_symbolic}: + + Copies the contents of the {\tt Symbolic} object (the initial row and column + preordering, supernodal column elimination tree, and information + about each frontal matrix) into arrays provided by the user. + +\item {\tt umfpack\_*\_get\_determinant}: + + Computes the determinant from the diagonal of $\m{U}$ and the permutations + $\m{P}$ and $\m{Q}$. This is mostly of theoretical interest. + It is not a good test to determine if your matrix is singular or not. + +\item {\tt umfpack\_*\_save\_numeric}: + + Saves a copy of the {\tt Numeric} object to a file, in binary format. + +\item {\tt umfpack\_*\_load\_numeric}: + + Creates a {\tt Numeric} object by loading it from a file created + by {\tt umfpack\_*\_save\_numeric}. + +\item {\tt umfpack\_*\_save\_symbolic}: + + Saves a copy of the {\tt Symbolic} object to a file, in binary format. + +\item {\tt umfpack\_*\_load\_symbolic}: + + Creates a {\tt Symbolic} object by loading it from a file created + by {\tt umfpack\_*\_save\_symbolic}. + +\end{itemize} + +UMFPACK itself does not make use of these routines; +they are provided solely for returning the contents of the opaque +{\tt Symbolic} and {\tt Numeric} objects to the user, and saving/loading +them to/from a binary file. None of them do any computation, except for +{\tt umfpack\_*\_get\_determinant}. + +%------------------------------------------------------------------------------- +\subsection{Reporting routines} +\label{Reporting} +%------------------------------------------------------------------------------- + +None of the UMFPACK routines discussed so far prints anything, even when an +error occurs. UMFPACK provides you with nine routines for printing the input +and output arguments (including the {\tt Control} settings and {\tt Info} +statistics) of UMFPACK routines discussed above. They are fully described in +Section~\ref{Report}: + +\begin{itemize} +\item {\tt umfpack\_*\_report\_status}: + + Prints the status (return value) of other {\tt umfpack\_*} routines. + +\item {\tt umfpack\_*\_report\_info}: + + Prints the statistics returned in the {\tt Info} array by + {\tt umfpack\_*\_*symbolic}, + {\tt umfpack\_*\_numeric}, and {\tt umfpack\_*\_*solve}. + +\item {\tt umfpack\_*\_report\_control}: + + Prints the {\tt Control} settings. + +\item {\tt umfpack\_*\_report\_matrix}: + + Verifies and prints a compressed column-form or compressed row-form sparse + matrix. + +\item {\tt umfpack\_*\_report\_triplet}: + + Verifies and prints a matrix in triplet form. + +\item {\tt umfpack\_*\_report\_symbolic}: + + Verifies and prints a {\tt Symbolic} object. + +\item {\tt umfpack\_*\_report\_numeric}: + + Verifies and prints a {\tt Numeric} object. + +\item {\tt umfpack\_*\_report\_perm}: + + Verifies and prints a permutation vector. + +\item {\tt umfpack\_*\_report\_vector}: + + Verifies and prints a real or complex vector. + +\end{itemize} + +The {\tt umfpack\_*\_report\_*} routines behave slightly differently when +compiled +into the C-callable UMFPACK library than when used in the MATLAB mexFunction. +MATLAB stores its sparse matrices using the same compressed column data +structure discussed above, where row and column indices of an $m$-by-$n$ +matrix are in the range 0 to $m-1$ or $n-1$, respectively\footnote{Complex +matrices in MATLAB use the split array form, with one {\tt double} array +for the real part and another array for the imaginary part. UMFPACK +supports that format, as well as the packed complex format (new to Version 4.4).} +It prints them as if they are in the range 1 to $m$ or $n$. +The UMFPACK mexFunction behaves the same way. + +You can control how much the {\tt umfpack\_*\_report\_*} routines print by +modifying the {\tt Control [UMFPACK\_PRL]} parameter. Its default value is 1. +Here is a summary of how the routines use this print level parameter: + +\begin{itemize} +\item {\tt umfpack\_*\_report\_status}: + + No output if the print level is 0 or less, even when an error occurs. + If 1, then error messages are printed, and nothing is printed if + the status is {\tt UMFPACK\_OK}. A warning message is printed if + the matrix is singular. If 2 or more, then the status is always + printed. If 4 or more, then the UMFPACK Copyright is printed. + If 6 or more, then the UMFPACK License is printed. See also the first page + of this User Guide for the Copyright and License. + +\item {\tt umfpack\_*\_report\_control}: + + No output if the print level is 1 or less. If 2 or more, all of + {\tt Control} is printed. + +\item {\tt umfpack\_*\_report\_info}: + + No output if the print level is 1 or less. If 2 or more, all of + {\tt Info} is printed. + +\item all other {\tt umfpack\_*\_report\_*} routines: + + If the print level is 2 or less, then these routines return silently without + checking their inputs. If 3 or more, the inputs are fully verified and a + short status summary is printed. If 4, then the first few entries of the + input arguments are printed. If 5, then all of the input arguments are + printed. + +\end{itemize} + +This print level parameter has an additional effect on the MATLAB mexFunction. +If zero, then no warnings of singular or nearly singular matrices are +printed (similar to the MATLAB commands +{\tt warning off MATLAB:singularMatrix} and +{\tt warning off MATLAB:nearlySingularMatrix}). + +%------------------------------------------------------------------------------- +\subsection{Utility routines} +%------------------------------------------------------------------------------- + +UMFPACK v4.0 included a routine that returns the time used by the process, +{\tt umfpack\_timer}. The routine uses either {\tt getrusage} (which is +preferred), or the ANSI C {\tt clock} routine if that is not available. +It is fully described in Section~\ref{Utility}. It is still available in +UMFPACK v4.1 and following, but not used internally. +Two new timing routines are provided in UMFPACK Version 4.1 and following, +{\tt umfpack\_tic} and {\tt umfpack\_toc}. They use POSIX-compliant +{\tt sysconf} and {\tt times} routines to find both the CPU time +and wallclock time. +These three routines are the only user-callable +routine that is identical in all four {\tt int}/{\tt long}, real/complex +versions (there is no {\tt umfpack\_di\_timer} routine, for example). + +%------------------------------------------------------------------------------- +\subsection{Control parameters} +\label{control_param} +%------------------------------------------------------------------------------- + +UMFPACK uses an optional {\tt double} array (currently of size 20) +to modify its control parameters. If you pass {\tt (double *) NULL} instead +of a {\tt Control} array, then defaults are used. These defaults provide +nearly optimal performance (both speed, memory usage, and numerical accuracy) +for a wide range of matrices from real applications. + +This array will almost certainly grow in size in future releases, +so be sure to dimension your {\tt Control} array to be of size +{\tt UMFPACK\_CONTROL}. That constant is currently defined to be 20, +but may increase in future versions, since all 20 entries are in use. + +The contents of this array may be modified by the user +(see {\tt umfpack\_*\_defaults}). Each +user-callable routine includes a complete description of how each control +setting modifies its behavior. Table~\ref{control} summarizes the entire +contents of the {\tt Control} array. +Note that ANSI C uses 0-based indexing, while MATLAB uses 1-based +indexing. Thus, {\tt Control(1)} in MATLAB is the same as +{\tt Control[0]} or {\tt Control[UMFPACK\_PRL]} in ANSI C. + +\begin{table} +\caption{UMFPACK Control parameters} +\label{control} +{\footnotesize +\begin{tabular}{llll} +\hline + +MATLAB & ANSI C & default & description \\ +\hline +{\tt Control(1)} & {\tt Control[UMFPACK\_PRL]} & 1 & printing level \\ +{\tt Control(2)} & {\tt Control[UMFPACK\_DENSE\_ROW]} & 0.2 & dense row parameter \\ +{\tt Control(3)} & {\tt Control[UMFPACK\_DENSE\_COL]} & 0.2 & dense column parameter \\ +{\tt Control(4)} & {\tt Control[UMFPACK\_PIVOT\_TOLERANCE]} & 0.1 & partial pivoting tolerance \\ +{\tt Control(5)} & {\tt Control[UMFPACK\_BLOCK\_SIZE]} & 32 & BLAS block size \\ +{\tt Control(6)} & {\tt Control[UMFPACK\_STRATEGY]} & 0 (auto) & select strategy \\ +{\tt Control(7)} & {\tt Control[UMFPACK\_ALLOC\_INIT]} & 0.7 & initial memory allocation \\ +{\tt Control(8)} & {\tt Control[UMFPACK\_IRSTEP]} & 2 & max iter. refinement steps \\ +{\tt Control(13)} & {\tt Control[UMFPACK\_2BY2\_TOLERANCE]} & 0.01 & defines ``large'' entries \\ +{\tt Control(14)} & {\tt Control[UMFPACK\_FIXQ]} & 0 (auto) & fix or modify Q \\ +{\tt Control(15)} & {\tt Control[UMFPACK\_AMD\_DENSE]} & 10 & AMD dense row/column parameter \\ +{\tt Control(16)} & {\tt Control[UMFPACK\_SYM\_PIVOT\_TOLERANCE]} & 0.001 & for diagonal entries \\ +{\tt Control(17)} & {\tt Control[UMFPACK\_SCALE]} & 1 (sum) & row scaling (none, sum, or max) \\ +{\tt Control(18)} & {\tt Control[UMFPACK\_FRONT\_ALLOC\_INIT]} & 0.5 & frontal matrix allocation ratio \\ +{\tt Control(19)} & {\tt Control[UMFPACK\_DROPTOL]} & 0 & drop tolerance \\ +{\tt Control(20)} & {\tt Control[UMFPACK\_AGGRESSIVE]} & 1 (yes) & aggressive absorption \\ + & & & in AMD and COLAMD \\ +% +\hline +\multicolumn{4}{l}{Can only be changed at compile time:} \\ +{\tt Control(9)} & {\tt Control[UMFPACK\_COMPILED\_WITH\_BLAS]} & - & true if BLAS is used \\ +{\tt Control(10)} & {\tt Control[UMFPACK\_COMPILED\_FOR\_MATLAB]} & - & true for mexFunction \\ +{\tt Control(11)} & {\tt Control[UMFPACK\_COMPILED\_WITH\_GETRUSAGE]} & - & 1 if {\tt getrusage} used \\ +{\tt Control(12)} & {\tt Control[UMFPACK\_COMPILED\_IN\_DEBUG\_MODE]} & - & true if debug mode enabled \\ +\hline +\end{tabular} +} +\end{table} + +Let $\alpha_r = ${\tt Control [UMFPACK\_DENSE\_ROW]}, + $\alpha_c = ${\tt Control [UMFPACK\_DENSE\_COL]}, and + $\alpha = ${\tt Control [UMFPACK\_AMD\_DENSE]}. +Suppose the submatrix $\m{S}$, obtained after eliminating pivots with +zero Markowitz cost, is $m$-by-$n$. +Then a row is considered ``dense'' if it has more than +$\max (16, 16 \alpha_r \sqrt{n})$ entries. +A column is considered ``dense'' if it has more than +$\max (16, 16 \alpha_c \sqrt{m})$ entries. +These rows and columns are treated different in COLAMD and during numerical +factorization. In COLAMD, dense columns are placed last in their natural +order, and dense rows are ignored. During numerical factorization, dense +rows are stored differently. +In AMD, a row/column of the square matrix $\m{S}+\m{S}\tr$ is +considered ``dense'' if it has more than $\max (16, \alpha \sqrt{n})$ entries. +These rows/columns are placed last in AMD's output ordering. +For more details on the control parameters, refer to the documentation of +{\tt umfpack\_*\_qsymbolic}, {\tt umfpack\_*\_numeric}, {\tt umfpack\_*\_solve}, +and the {\tt umfpack\_*\_report\_*} routines, +in Sections~\ref{Primary}~through~\ref{Report}, below. + +%------------------------------------------------------------------------------- +\subsection{Error codes} +\label{error_codes} +%------------------------------------------------------------------------------- + +Many of the routines return a {\tt status} value. +This is also returned as the first entry in the {\tt Info} array, for +those routines with that argument. The following list summarizes +all of the error codes in UMFPACK. Each error code is given a +specific name in the {\tt umfpack.h} include file, so you can use +those constants instead of hard-coded values in your program. +Future versions may report additional error codes. + +A value of zero means everything was successful, and the matrix is +non-singular. A value greater than zero means the routine was successful, +but a warning occurred. +A negative value means the routine was not successful. +In this case, no {\tt Symbolic} or {\tt Numeric} object was created. + +\begin{itemize} +\item {\tt UMFPACK\_OK}, (0): UMFPACK was successful. + +\item {\tt UMFPACK\_WARNING\_singular\_matrix}, (1): Matrix is singular. + There are exact zeros on the diagonal of $\m{U}$. + +\item {\tt UMFPACK\_WARNING\_determinant\_underflow}, (2): + The determinant is nonzero, but smaller in magnitude than + the smallest positive floating-point number. + +\item {\tt UMFPACK\_WARNING\_determinant\_overflow}, (3): + The determinant is larger in magnitude than + the largest positive floating-point number (IEEE Inf). + +\item {\tt UMFPACK\_ERROR\_out\_of\_memory}, (-1): Not enough memory. + The ANSI C {\tt malloc} or {\tt realloc} routine failed. + +\item {\tt UMFPACK\_ERROR\_invalid\_Numeric\_object}, (-3): + Routines that take a {\tt Numeric} object as input (or load it + from a file) check this object and return this error code if it is + invalid. This can be caused by a memory leak or overrun in your + program, which can overwrite part of the Numeric object. It can also + be caused by passing a Symbolic object by mistake, or some other pointer. + If you try to factorize a matrix using one version of UMFPACK and + then use the factors in another version, this error code will trigger as + well. You cannot factor your matrix using + version 4.0 and then solve with version 4.1, for example.\footnote{ + Exception: v4.3, v4.3.1, and v4.4 use identical data structures + for the {\tt Numeric} and {\tt Symbolic} objects}. + You cannot use different precisions of the same version + (real and complex, for example). + It is possible for the {\tt Numeric} object to be corrupted by your + program in subtle ways that are not detectable by this quick check. + In this case, you may see an + {\tt UMFPACK\_ERROR\_different\_pattern} error code, or even an + {\tt UMFPACK\_ERROR\_internal\_error}. + +\item {\tt UMFPACK\_ERROR\_invalid\_Symbolic\_object}, (-4): + Routines that take a {\tt Symbolic} object as input (or load it + from a file) check this object and return this error code if it is + invalid. The causes of this error are analogous to the + {\tt UMFPACK\_ERROR\_invalid\_Numeric\_object} error described above. + +\item {\tt UMFPACK\_ERROR\_argument\_missing}, (-5): + Some arguments of some are optional (you can pass a {\tt NULL} pointer + instead of an array). This error code occurs if you pass a {\tt NULL} + pointer when that argument is required to be present. + +\item {\tt UMFPACK\_ERROR\_n\_nonpositive} (-6): + The number of rows or columns of the matrix must be greater than zero. + +\item {\tt UMFPACK\_ERROR\_invalid\_matrix} (-8): + The matrix is invalid. For the column-oriented input, this error + code will occur if the contents of {\tt Ap} and/or {\tt Ai} are invalid. + + {\tt Ap} is an integer array of size {\tt n\_col+1}. + On input, it holds the + ``pointers'' for the column form of the sparse matrix $\m{A}$. + Column {\tt j} of + the matrix A is held in {\tt Ai [(Ap [j])} \ldots {\tt (Ap [j+1]-1)]}. + The first entry, {\tt Ap [0]}, must be zero, + and {\tt Ap [j]} $\le$ {\tt Ap [j+1]} must hold for all + {\tt j} in the range 0 to {\tt n\_col-1}. + The value {\tt nz = Ap [n\_col]} is thus the + total number of entries in the pattern of the matrix A. + {\tt nz} must be greater than or equal to zero. + + The nonzero pattern (row indices) for column {\tt j} is stored in + {\tt Ai [(Ap [j])} \ldots {\tt (Ap [j+1]-1)]}. The row indices in a given + column {\tt j} + must be in ascending order, and no duplicate row indices may be present. + Row indices must be in the range 0 to {\tt n\_row-1} + (the matrix is 0-based). + + Some routines take a triplet-form input, with arguments + {\tt nz}, {\tt Ti}, and {\tt Tj}. This error code is returned + if {\tt nz} is less than zero, + if any row index in {\tt Ti} is outside the range 0 to {\tt n\_col-1}, or + if any column index in {\tt Tj} is outside the range 0 to {\tt n\_row-1}. + +\item {\tt UMFPACK\_ERROR\_different\_pattern}, (-11): + The most common cause of this error is that the pattern of the + matrix has changed between the symbolic and numeric factorization. + It can also occur if the {\tt Numeric} or {\tt Symbolic} object has + been subtly corrupted by your program. + +\item {\tt UMFPACK\_ERROR\_invalid\_system}, (-13): + The {\tt sys} argument provided to one of the solve routines is invalid. + +\item {\tt UMFPACK\_ERROR\_invalid\_permutation}, (-15): + The permutation vector provided as input is invalid. + +\item {\tt UMFPACK\_ERROR\_file\_IO}, (-17): + This error code is returned by the routines that save and load + the {\tt Numeric} or {\tt Symbolic} objects to/from a file, if a + file I/O error has occurred. The file may not exist or may not be readable, + you may be trying to create a file that you don't have permission to create, + or you may be out of disk space. The file you are trying to read might + be the wrong one, and an earlier end-of-file condition would then result + in this error. + +\item {\tt UMFPACK\_ERROR\_internal\_error}, (-911): + An internal error has occurred, of unknown cause. This is either a bug + in UMFPACK, or the result of a memory overrun from your program. + Try modifying the file {\tt AMD/Source/amd\_internal.h} and adding + the statement {\tt \#undef NDEBUG}, to enable the debugging mode. + Recompile UMFPACK and rerun your program. + A failed assertion might occur which + can give you a better indication as to what is going wrong. Be aware that + UMFPACK will be extraordinarily slow when running in debug mode. + If all else fails, contact the developer (davis@cise.ufl.edu) with + as many details as possible. + +\end{itemize} + +%------------------------------------------------------------------------------- +\subsection{Larger examples} +%------------------------------------------------------------------------------- + +Full examples of all user-callable UMFPACK routines +are available in four stand-alone C main programs, {\tt umfpack\_*\_demo.c}. +Another example is +the UMFPACK mexFunction, {\tt umfpackmex.c}. The mexFunction accesses only the +user-callable C interface to UMFPACK. The only features that it does not use +are the support for the triplet form (MATLAB's sparse arrays are already in the +compressed column form) and the ability to reuse the {\tt Symbolic} object to +numerically factorize a matrix whose pattern is the same as a prior matrix +analyzed by {\tt umfpack\_*\_symbolic} or {\tt umfpack\_*\_qsymbolic}. The +latter is an important feature, but the mexFunction does not return its opaque +{\tt Symbolic} and {\tt Numeric} objects to MATLAB. Instead, it gets the +contents of these objects after extracting them via the {\tt umfpack\_*\_get\_*} +routines, and returns them as MATLAB sparse matrices. + +The {\tt umf4.c} program for reading matrices in Harwell/Boeing format +\cite{DuffGrimesLewis87b} is provided. It requires three Fortran 77 programs +({\tt readhb.f}, {\tt readhb\_nozeros.f}, and {\tt readhb\_size.f}) +for reading in the sample Harwell/Boeing files in the {\tt UMFPACK/Demo/HB} +directory. More matrices are available at +http://www.cise.ufl.edu/research/sparse/matrices. +Type {\tt make hb} in the {\tt UMFPACK/Demo/HB} directory +to compile and run this demo. This program was used for the experimental +results in \cite{Davis03}. + +%------------------------------------------------------------------------------- +\section{Synopsis of C-callable routines} +\label{Synopsis} +%------------------------------------------------------------------------------- + +Each subsection, below, summarizes the input variables, output variables, return +values, and calling sequences of the routines in one category. Variables with +the same name as those already listed in a prior category have the same size +and type. + +The real, {\tt long} integer {\tt umfpack\_dl\_*} routines are +identical to the real, {\tt int} routines, except that {\tt \_di\_} is replaced +with {\tt \_dl\_} in the name, and all {\tt int} arguments become {\tt long}. +Similarly, the complex, {\tt long} integer {\tt umfpack\_zl\_*} routines are +identical to the complex, {\tt int} routines, except that {\tt \_zi\_} is +replaced +with {\tt \_zl\_} in the name, and all {\tt int} arguments become {\tt long}. +Only the real and complex {\tt int} versions are listed in the synopsis below. + +The matrix $\m{A}$ is {\tt m}-by-{\tt n} with {\tt nz} entries. + +The {\tt sys} argument of {\tt umfpack\_*\_solve} +is an integer in the range 0 to 14 which defines which linear system is +to be solved. +\footnote{Integer values for {\tt sys} are used instead of strings (as in LINPACK +and LAPACK) to avoid C-to-Fortran portability issues.} +Valid values are listed in Table~\ref{sys}. +The notation $\m{A}\he$ refers to the matrix transpose, which is the +complex conjugate transpose for complex matrices ({\tt A'} in MATLAB). +The array transpose is $\m{A}\tr$, which is {\tt A.'} in MATLAB. + +\begin{table} +\begin{center} +\caption{UMFPACK {\tt sys} parameter} +\label{sys} +{\footnotesize +\begin{tabular}{ll|l} +\hline +Value & & system \\ +\hline +& & \\ +{\tt UMFPACK\_A} & (0) & $\m{Ax}=\m{b}$ \\ +{\tt UMFPACK\_At} & (1) & $\m{A}\he\m{x}=\m{b}$ \\ +{\tt UMFPACK\_Aat} & (2) & $\m{A}\tr\m{x}=\m{b}$ \\ +& & \\ +\hline +& & \\ +{\tt UMFPACK\_Pt\_L} & (3) & $\m{P}\tr\m{Lx}=\m{b}$ \\ +{\tt UMFPACK\_L} & (4) & $\m{Lx}=\m{b}$ \\ +{\tt UMFPACK\_Lt\_P} & (5) & $\m{L}\he\m{Px}=\m{b}$ \\ +{\tt UMFPACK\_Lat\_P} & (6) & $\m{L}\tr\m{Px}=\m{b}$ \\ +{\tt UMFPACK\_Lt} & (7) & $\m{L}\he\m{x}=\m{b}$ \\ +{\tt UMFPACK\_Lat} & (8) & $\m{L}\tr\m{x}=\m{b}$ \\ +& & \\ +\hline +& & \\ +{\tt UMFPACK\_U\_Qt} & (9) & $\m{UQ}\tr\m{x}=\m{b}$ \\ +{\tt UMFPACK\_U} & (10) & $\m{Ux}=\m{b}$ \\ +{\tt UMFPACK\_Q\_Ut} & (11) & $\m{QU}\he\m{x}=\m{b}$ \\ +{\tt UMFPACK\_Q\_Uat} & (12) & $\m{QU}\tr\m{x}=\m{b}$ \\ +{\tt UMFPACK\_Ut} & (13) & $\m{U}\he\m{x}=\m{b}$ \\ +{\tt UMFPACK\_Uat} & (14) & $\m{U}\tr\m{x}=\m{b}$ \\ +& & \\ +\hline +\end{tabular} +} +\end{center} +\end{table} + +%------------------------------------------------------------------------------- +\subsection{Primary routines: real/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +#include "umfpack.h" +int status, sys, n, m, nz, Ap [n+1], Ai [nz] ; +double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], Ax [nz], X [n], B [n] ; +void *Symbolic, *Numeric ; + +status = umfpack_di_symbolic (m, n, Ap, Ai, Ax, &Symbolic, Control, Info) ; +status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info) ; +status = umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ; +umfpack_di_free_symbolic (&Symbolic) ; +umfpack_di_free_numeric (&Numeric) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{Alternative routines: real/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +int Qinit [n], Wi [n] ; +double W [5*n] ; + +umfpack_di_defaults (Control) ; +status = umfpack_di_qsymbolic (m, n, Ap, Ai, Ax, Qinit, &Symbolic, Control, Info) ; +status = umfpack_di_wsolve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info, Wi, W) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{Matrix manipulation routines: real/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +int Ti [nz], Tj [nz], P [m], Q [n], Rp [m+1], Ri [nz], Map [nz] ; +double Tx [nz], Rx [nz], Y [m], Z [m] ; + +status = umfpack_di_col_to_triplet (n, Ap, Tj) ; +status = umfpack_di_triplet_to_col (m, n, nz, Ti, Tj, Tx, Ap, Ai, Ax, Map) ; +status = umfpack_di_transpose (m, n, Ap, Ai, Ax, P, Q, Rp, Ri, Rx) ; +status = umfpack_di_scale (Y, Z, Numeric) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{Getting the contents of opaque objects: real/{\tt int}} +%------------------------------------------------------------------------------- + +The {\tt filename} string should be large enough to hold the name of a file. + +{\footnotesize +\begin{verbatim} +int lnz, unz, Lp [m+1], Lj [lnz], Up [n+1], Ui [unz], do_recip ; +double Lx [lnz], Ux [unz], D [min (m,n)], Rs [m], Mx [1], Ex [1] ; +int nfr, nchains, P1 [m], Q1 [n], Front_npivcol [n+1], Front_parent [n+1], Front_1strow [n+1], + Front_leftmostdesc [n+1], Chain_start [n+1], Chain_maxrows [n+1], Chain_maxcols [n+1] ; +char filename [100] ; + +status = umfpack_di_get_lunz (&lnz, &unz, &m, &n, &nz_udiag, Numeric) ; +status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, D, + &do_recip, Rs, Numeric) ; +status = umfpack_di_get_symbolic (&m, &n, &n1, &nz, &nfr, &nchains, P1, Q1, + Front_npivcol, Front_parent, Front_1strow, Front_leftmostdesc, + Chain_start, Chain_maxrows, Chain_maxcols, Symbolic) ; +status = umfpack_di_load_numeric (&Numeric, filename) ; +status = umfpack_di_save_numeric (Numeric, filename) ; +status = umfpack_di_load_symbolic (&Symbolic, filename) ; +status = umfpack_di_save_symbolic (Symbolic, filename) ; +status = umfapck_di_get_determinant (Mx, Ex, Numeric, Info) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{Reporting routines: real/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} + +umfpack_di_report_status (Control, status) ; +umfpack_di_report_control (Control) ; +umfpack_di_report_info (Control, Info) ; +status = umfpack_di_report_matrix (m, n, Ap, Ai, Ax, 1, Control) ; +status = umfpack_di_report_matrix (m, n, Rp, Ri, Rx, 0, Control) ; +status = umfpack_di_report_numeric (Numeric, Control) ; +status = umfpack_di_report_perm (m, P, Control) ; +status = umfpack_di_report_perm (n, Q, Control) ; +status = umfpack_di_report_symbolic (Symbolic, Control) ; +status = umfpack_di_report_triplet (m, n, nz, Ti, Tj, Tx, Control) ; +status = umfpack_di_report_vector (n, X, Control) ; +\end{verbatim} +} + + + + + + +%------------------------------------------------------------------------------- +\subsection{Primary routines: complex/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +double Az [nz], Xx [n], Xz [n], Bx [n], Bz [n] ; + +status = umfpack_zi_symbolic (m, n, Ap, Ai, Ax, Az, &Symbolic, Control, Info) ; +status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, Control, Info) ; +status = umfpack_zi_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, Control, Info) ; +umfpack_zi_free_symbolic (&Symbolic) ; +umfpack_zi_free_numeric (&Numeric) ; +\end{verbatim} +} + +The arrays {\tt Ax}, {\tt Bx}, and {\tt Xx} double in size if +any imaginary argument ({\tt Az}, {\tt Xz}, or {\tt Bz}) is {\tt NULL}. + +%------------------------------------------------------------------------------- +\subsection{Alternative routines: complex/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +double Wz [10*n] ; + +umfpack_zi_defaults (Control) ; +status = umfpack_zi_qsymbolic (m, n, Ap, Ai, Ax, Az, Qinit, &Symbolic, Control, Info) ; +status = umfpack_zi_wsolve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, Control, Info, Wi, Wz) ; +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{Matrix manipulation routines: complex/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +double Tz [nz], Rz [nz], Yx [m], Yz [m], Zx [m], Zz [m] ; + +status = umfpack_zi_col_to_triplet (n, Ap, Tj) ; +status = umfpack_zi_triplet_to_col (m, n, nz, Ti, Tj, Tx, Tz, Ap, Ai, Ax, Az, Map) ; +status = umfpack_zi_transpose (m, n, Ap, Ai, Ax, Az, P, Q, Rp, Ri, Rx, Rz, 1) ; +status = umfpack_zi_transpose (m, n, Ap, Ai, Ax, Az, P, Q, Rp, Ri, Rx, Rz, 0) ; +status = umfpack_zi_scale (Yx, Yz, Zx, Zz, Numeric) ; +\end{verbatim} +} + +The arrays {\tt Tx}, {\tt Rx}, {\tt Yx}, and {\tt Zx} double in size if +any imaginary argument ({\tt Tz}, {\tt Rz}, {\tt Yz}, or {\tt Zz}) is {\tt NULL}. + +%------------------------------------------------------------------------------- +\subsection{Getting the contents of opaque objects: complex/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} +double Lz [lnz], Uz [unz], Dx [min (m,n)], Dz [min (m,n)], Mz [1] ; + +status = umfpack_zi_get_lunz (&lnz, &unz, &m, &n, &nz_udiag, Numeric) ; +status = umfpack_zi_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, P, Q, Dx, Dz, + &do_recip, Rs, Numeric) ; +status = umfpack_zi_get_symbolic (&m, &n, &n1, &nz, &nfr, &nchains, P1, Q1, + Front_npivcol, Front_parent, Front_1strow, Front_leftmostdesc, + Chain_start, Chain_maxrows, Chain_maxcols, Symbolic) ; +status = umfpack_zi_load_numeric (&Numeric, filename) ; +status = umfpack_zi_save_numeric (Numeric, filename) ; +status = umfpack_zi_load_symbolic (&Symbolic, filename) ; +status = umfpack_zi_save_symbolic (Symbolic, filename) ; +status = umfapck_zi_get_determinant (Mx, Mz, Ex, Numeric, Info) ; +\end{verbatim} +} + +The arrays {\tt Lx}, {\tt Ux}, {\tt Dx}, and {\tt Mx} double in size if +any imaginary argument ({\tt Lz}, {\tt Uz}, {\tt Dz}, or {\tt Mz}) is {\tt NULL}. + +%------------------------------------------------------------------------------- +\subsection{Reporting routines: complex/{\tt int}} +%------------------------------------------------------------------------------- + +{\footnotesize +\begin{verbatim} + +umfpack_zi_report_status (Control, status) ; +umfpack_zi_report_control (Control) ; +umfpack_zi_report_info (Control, Info) ; +status = umfpack_zi_report_matrix (m, n, Ap, Ai, Ax, Az, 1, Control) ; +status = umfpack_zi_report_matrix (m, n, Rp, Ri, Rx, Rz, 0, Control) ; +status = umfpack_zi_report_numeric (Numeric, Control) ; +status = umfpack_zi_report_perm (m, P, Control) ; +status = umfpack_zi_report_perm (n, Q, Control) ; +status = umfpack_zi_report_symbolic (Symbolic, Control) ; +status = umfpack_zi_report_triplet (m, n, nz, Ti, Tj, Tx, Tz, Control) ; +status = umfpack_zi_report_vector (n, Xx, Xz, Control) ; +\end{verbatim} +} + +The arrays {\tt Ax}, {\tt Rx}, {\tt Tx}, and {\tt Xx} double in size if +any imaginary argument ({\tt Az}, {\tt Rz}, {\tt Tz}, or {\tt Xz}) is {\tt NULL}. + + + + +%------------------------------------------------------------------------------- +\subsection{Utility routines} +%------------------------------------------------------------------------------- + +These routines are the same in all four versions of UMFPACK. + +{\footnotesize +\begin{verbatim} +double t, s [2] ; + +t = umfpack_timer ( ) ; +umfpack_tic (s) ; +umfpack_toc (s) ; + +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\subsection{AMD ordering routines} +%------------------------------------------------------------------------------- + +UMFPACK makes use of the AMD ordering package for its symmetric ordering +strategy. You may also use these four user-callable routines in your own C +programs. You need to include the {\tt amd.h} file only if you make direct +calls to the AMD routines themselves. The {\tt int} versions are summarized +below; {\tt long} versions are also available. Refer to the AMD User Guide +for more information, or to the file {\tt amd.h} which documents these routines. + +{\footnotesize +\begin{verbatim} +#include "amd.h" +double amd_control [AMD_CONTROL], amd_info [AMD_INFO] ; + +amd_defaults (amd_control) ; +status = amd_order (n, Ap, Ai, P, amd_control, amd_info) ; +amd_control (amd_control) ; +amd_info (amd_info) ; + +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\section{Using UMFPACK in a Fortran program} +%------------------------------------------------------------------------------- + +UMFPACK includes a basic Fortran 77 interface to some of the C-callable +UMFPACK routines. +Since interfacing C and Fortran programs is not portable, this interface might +not work with all C and Fortran compilers. Refer to Section~\ref{Install} for +more details. The following Fortran routines are provided. +The list includes the C-callable routines that the Fortran interface +routine calls. Refer to the corresponding C routines in Section~\ref{C} for +more details on what the Fortran routine does. + +\begin{itemize} +\item {\tt umf4def}: sets the default control parameters + ({\tt umfpack\_di\_defaults}). + +\item {\tt umf4sym}: pre-ordering and symbolic factorization + ({\tt umfpack\_di\_symbolic}). + +\item {\tt umf4num}: numeric factorization + ({\tt umfpack\_di\_numeric}). + +\item {\tt umf4solr}: solve a linear system with iterative refinement + ({\tt umfpack\_di\_solve}). + +\item {\tt umf4sol}: solve a linear system without iterative refinement + ({\tt umfpack\_di\_solve}). Sets {\tt Control [UMFPACK\_IRSTEP]} + to zero, and does not require the matrix $\m{A}$. + +\item {\tt umf4scal}: scales a vector using UMFPACK's scale factors + ({\tt umfpack\_di\_scale}). + +\item {\tt umf4fnum}: free the {\tt Numeric} object + ({\tt umfpack\_di\_free\_numeric}). + +\item {\tt umf4fsym}: free the {\tt Symbolic} object + ({\tt umfpack\_di\_free\_symbolic}). + +\item {\tt umf4pcon}: prints the control parameters + ({\tt umfpack\_di\_report\_control}). + +\item {\tt umf4pinf}: print statistics + ({\tt umfpack\_di\_report\_info}). + +\item {\tt umf4snum}: save the {\tt Numeric} object to a file + ({\tt umfpack\_di\_save\_numeric}). + +\item {\tt umf4ssym}: save the {\tt Symbolic} object to a file + ({\tt umfpack\_di\_save\_symbolic}). + +\item {\tt umf4lnum}: load the {\tt Numeric} object from a file + ({\tt umfpack\_di\_load\_numeric}). + +\item {\tt umf4lsym}: load the {\tt Symbolic} object from a file + ({\tt umfpack\_di\_load\_symbolic}). +\end{itemize} + +The matrix $\m{A}$ is passed to UMFPACK in compressed column form, with 0-based +indices. In Fortran, for an {\tt m}-by-{\tt n} matrix $\m{A}$ with {\tt nz} +entries, the row indices of the first column (column 1) are in +{\tt Ai (Ap(1)+1} \ldots {\tt Ap(2))}, with values in +{\tt Ax (Ap(1)+1} \ldots {\tt Ap(2))}. The last column (column {\tt n}) is in +{\tt Ai (Ap(n)+1} \ldots {\tt Ap(n+1))} and +{\tt Ax (Ap(n)+1} \ldots {\tt Ap(n+1))}. +The number of entries in the matrix is thus {\tt nz = Ap (n+1)}. +The row indices in {\tt Ai} are in the range 0 to {\tt m}-1. They must be +sorted, with no duplicate entries allowed. None of the UMFPACK routines +modify the input matrix $\m{A}$. +The following definitions apply for the Fortran routines: + +{\footnotesize +\begin{verbatim} + integer m, n, Ap (n+1), Ai (nz), symbolic, numeric, filenum, status + double precision Ax (nz), control (20), info (90), x (n), b (n) +\end{verbatim} +} + +UMFPACK's status is returned in either a {\tt status} argument, or in +{\tt info (1)}. +It is zero if UMFPACK was successful, 1 if the matrix is singular (this is a +warning, not an error), and negative if an error occurred. +Section~\ref{error_codes} summarizes the possible values of {\tt status} +and {\tt info (1)}. +See Table~\ref{sys} for a list of the values of the {\tt sys} argument. +See Table~\ref{control} for a list of the control parameters (the +Fortran usage is the same as the MATLAB usage for this array). + +For the {\tt Numeric} and {\tt Symbolic} handles, it is probably safe to +assume that a Fortran {\tt integer} is sufficient to store a C pointer. If +that does not work, try defining {\tt numeric} and {\tt symbolic} in your +Fortran program as integer arrays of size 2. You will need to define them +as {\tt integer*8} if you compile UMFPACK in the 64-bit mode. + +To avoid passing strings between C and Fortran in the load/save routines, +a file number is passed instead, and the C interface constructs a file name +(if {\tt filenum} is 42, the {\tt Numeric} file name is {\tt n42.umf}, and +the {\tt Symbolic} file name is {\tt s42.umf}). + +The following is a summary of the calling sequence of each Fortran +interface routine. An example of their use is in the {\tt Demo/umf4hb.f} +file. That routine also includes an example of how to convert a 1-based +sparse matrix into 0-based form. For more details on the arguments of each +routine, refer to the arguments of the same name in the corresponding +C-callable routine, in Sections~\ref{Primary}~through~\ref{Utility}. +The only exception is the {\tt control} argument of {\tt umf4sol}, +which sets {\tt control (8)} to zero to disable iterative refinement. +Note that the solve routines do not overwrite {\tt b} with the solution, +but return their solution in a different array, {\tt x}. + +{\footnotesize +\begin{verbatim} + call umf4def (control) + call umf4sym (m, n, Ap, Ai, Ax, symbolic, control, info) + call umf4num (Ap, Ai, Ax, symbolic, numeric, control, info) + call umf4solr (sys, Ap, Ai, Ax, x, b, numeric, control, info) + call umf4sol (sys, x, b, numeric, control, info) + call umf4scal (x, b, numeric, status) + call umf4fnum (numeric) + call umf4fsym (symbolic) + call umf4pcon (control) + call umf4pinf (control) + call umf4snum (numeric, filenum, status) + call umf4ssym (symbolic, filenum, status) + call umf4lnum (numeric, filenum, status) + call umf4lsym (symbolic, filenum, status) +\end{verbatim} +} + +Access to the complex routines in UMFPACK is provided by the interface +routines in {\tt umf4\_f77zwrapper.c}. The following is a synopsis +of each routine. All the arguments are the same as the real versions, +except {\tt Az}, {\tt xz}, and {\tt bz} are the imaginary parts of +the matrix, solution, and right-hand-side, respectively. The +{\tt Ax}, {\tt x}, and {\tt b} are the real parts. + +{\footnotesize +\begin{verbatim} + call umf4zdef (control) + call umf4zsym (m, n, Ap, Ai, Ax, Az, symbolic, control, info) + call umf4znum (Ap, Ai, Ax, Az, symbolic, numeric, control, info) + call umf4zsolr (sys, Ap, Ai, Ax, Az, x, xz, b, bz, numeric, control, info) + call umf4zsol (sys, x, xz, b, bz, numeric, control, info) + call umf4zscal (x, xz, b, bz, numeric, status) + call umf4zfnum (numeric) + call umf4zfsym (symbolic) + call umf4zpcon (control) + call umf4zpinf (control) + call umf4zsnum (numeric, filenum, status) + call umf4zssym (symbolic, filenum, status) + call umf4zlnum (numeric, filenum, status) + call umf4zlsym (symbolic, filenum, status) +\end{verbatim} +} + +The Fortran interface does not support the packed complex case. + +%------------------------------------------------------------------------------- +\section{Installation} +\label{Install} +%------------------------------------------------------------------------------- + +%------------------------------------------------------------------------------- +\subsection{Installing the C library} +%------------------------------------------------------------------------------- + +The following discussion assumes you have the {\tt make} program, either in +Unix, or in Windows with Cygwin\footnote{www.cygwin.com}. +You can skip this section and go to next one if all you want to use is +the UMFPACK and AMD mexFunctions in MATLAB. + +You will need to install both UMFPACK v4.4 and AMD v1.1 (or AMD v1.0) to use UMFPACK. +The {\tt UMFPACK} and {\tt AMD} subdirectories must be placed side-by-side +within the same directory. AMD is a stand-alone package that +is required by UMFPACK. UMFPACK can be compiled without the +BLAS \cite{DaydeDuff99,ACM679a,ATLAS,GotoVandeGeijn02}, +but your performance will be much less than what it should be. + +System-dependent configurations are in the {\tt AMD/Make} +and {\tt UMFPACK/Make} directories (the \newline +{\tt UMFPACK/Make} directory is actually +just a symbolic link to {\tt AMD/Make}\footnote{Windows might not extract +the symbolic link {\tt UMFPACK/Make} correctly. If it doesn't, simply +create the {\tt UMFPACK/Make} folder by copying it from {\tt AMD/Make}.}). +You can edit the {\tt Make.include} +files in either of those directories to customize the compilation. The default +settings will work on most systems, except that UMFPACK will be compiled so +that it does not use the BLAS. Sample configuration files are provided +for Linux, Sun Solaris, SGI IRIX, IBM AIX, and the DEC/Compaq Alpha. + +To compile and install both packages, +go to the {\tt UMFPACK} directory and type {\tt make}. This will compile the +libraries ({\tt AMD/Lib/libamd.a} and {\tt UMFPACK/Lib/libumfpack.a}). +A demo of the AMD ordering routine will be compiled and tested in +the {\tt AMD/Demo} directory, and five demo programs will then be +compiled and tested in the {\tt UMFPACK/Demo} directory. +The outputs of these demo programs will then be compared with output +files in the distribution. Expect to see a few differences, such as +residual norms, compile-time control settings, and perhaps memory usage +differences. The AMD and UMFPACK mexFunctions for +use in MATLAB will also be compiled. If you do not have MATLAB 6.0 or +later, type {\tt make lib} instead. + +If you have the GNU version of {\tt make}, the {\tt Source/GNUmakefile} and +{\tt MATLAB/GNUmakefile} files are used. These are much more concise than +what the ``old'' version of {\tt make} can handle. If you do not have +GNU {\tt make}, the {\tt Source/Makefile} and {\tt MATLAB/Makefile} files +are used instead. Each UMFPACK source file is compiled into four +versions ({\tt double} / complex, and {\tt int} / {\tt long}). A proper +old-style {\tt Makefile} is cumbersome in this case, so these two +{\tt Makefile}'s have been constructed by brute force. They ignore +dependencies, and simply compile everything. I highly recommend using GNU +{\tt make} if you wish to modify UMFPACK. + +If you compile UMFPACK and AMD and then later change the {\tt Make.include} +file or your system-specific configuration file such as {\tt Make.linux}, +then you should type {\tt make purge} and then {\tt make} to recompile. + +Here are the various parameters that you can control in your +{\tt Make.include} file: + +\begin{itemize} +\item {\tt CC = } your C compiler, such as {\tt cc}. +\item {\tt RANLIB = } your system's {\tt ranlib} program, if needed. +\item {\tt CFLAGS = } optimization flags, such as {\tt -O}. + Add {\tt -DLP64} if you are compiling in 64-bit mode + (32 bit {\tt int}'s, 64 bit {\tt long}'s, and 64 bit pointers). +\item {\tt CONFIG = } configuration settings for the BLAS, memory allocation + routines, and timing routines. +\item {\tt LIB = } your libraries, such as {\tt -lm} or {\tt -lblas}. +\item {\tt RM =} the command to delete a file. +\item {\tt MV =} the command to rename a file. +\item {\tt MEX =} the command to compile a MATLAB mexFunction. + If you are using MATLAB 5, you need to add {\tt -DNBLAS} and + {\tt -DNUTIL} to this command. An example is provided in + the {\tt Make/Make.include} file. +\item {\tt F77 =} the command to compile a Fortran program (optional). +\item {\tt F77FLAGS =} the Fortran compiler flags (optional). +\item {\tt F77LIB =} the Fortran libraries (optional). +\end{itemize} + +The {\tt CONFIG} string can include combinations of the following; +most deal with how the BLAS are called: +\begin{itemize} +\item {\tt -DNBLAS} if you do not have any BLAS at all. +\item {\tt -DCBLAS} if you have the C-BLAS \cite{ATLAS}. +\item {\tt -DNSUNPERF} if you are on Solaris but do not have the Sun + Performance Library (for the BLAS). +\item {\tt -DNSCSL} if you on SGI IRIX but do not have the SCSL BLAS library. +\item {\tt -DLONGBLAS} if your BLAS can take {\tt long} integer input + arguments. If not defined, then the {\tt umfpack\_*l\_*} versions of + UMFPACK that use {\tt long} integers do not call the BLAS. + This flag is set internally when using the Sun Performance BLAS + or SGI's SCSL BLAS (both have 64-bit versions of the BLAS). +\item Options for controlling how C calls the Fortran BLAS: + {\tt -DBLAS\_BY\_VALUE}, {\tt -DBLAS\_NO\_UNDERSCORE}, + and {\tt -DBLAS\_CHAR\_ARG}. These are set automatically for Windows, + Sun Solaris, SGI Irix, Red Hat Linux, Compaq Alpha, and + AIX (the IBM RS 6000). They are ignored if you are using + the C-BLAS interface to the BLAS. +\item {\tt -DGETRUSAGE} if you have the {\tt getrusage} function. +\item {\tt -DNUTIL} if you wish to compile the MATLAB-callable + UMFPACK mexFunction with the {\tt mxMalloc}, {\tt mxRealloc} + and {\tt mxFree} routines, instead of the undocumented (but + superior) {\tt utMalloc}, {\tt utRealloc}, and {\tt utFree} + routines. The default is to use the {\tt ut*} routines on + Unix, and the {\tt mx*} routines on Windows. +\item {\tt -DNPOSIX} if you do not have the POSIX-compliant + {\tt sysconf} and {\tt times} routines used by + {\tt umfpack\_tic} and {\tt umfpack\_toc}. +\item {\tt -DNRECIPROCAL} controls a trade-off between speed and accuracy. + If defined (or if the pivot value itself is less than $10^{-12}$), + then the pivot column is divided by the pivot value during numeric + factorization. Otherwise, it is multiplied by the reciprocal of the + pivot, which is faster but can be less accurate. The default is + to multiply by the reciprocal unless the pivot value is small. + This option also modifies how the rows of the matrix $\m{A}$ are + scaled. If {\tt -DNRECIPROCAL} is defined (or if any scale factor is + less than $10^{-12}$), entries in the rows of $\m{A}$ are divided + by the scale factors. Otherwise, they are multiplied by the reciprocal. + When compiling the complex routines with the GNU {\tt gcc} compiler, the + pivot column is always divided by the pivot entry, because of a + numerical accuracy issue encountered with {\tt gcc} version 3.2 with a + few complex matrices on a Pentium 4M (running Linux). You can still + use {\tt -DNRECIPROCAL} to control how the scale factors + for the rows of $\m{A}$ are applied. +\item {\tt -DNO\_DIVIDE\_BY\_ZERO} controls how UMFPACK treats zeros + on the diagonal of $\m{U}$, for a singular matrix $\m{A}$. + If defined, then no division by + zero is performed (a zero entry on the diagonal of $\m{U}$ is + treated as if it were equal to one). By default, + UMFPACK will divide by zero. +\item {\tt -DNO\_TIMER} controls whether or not timing routines + are to be called. If defined, no timers are used. + Timers are included by default. +\end{itemize} + +If a Fortran BLAS package is used you may see compiler warnings. The BLAS +routines +{\tt dgemm}, {\tt dgemv}, {\tt dger}, {\tt dtrsm}, {\tt dtrsv}, {\tt dscal} +and their corresponding complex versions are used. +Header files are not provided for the Fortran +BLAS. You may safely ignore all of these warnings. + +I highly recommend the recent BLAS by Goto and van de Geijn +\cite{GotoVandeGeijn02}. Using this BLAS increased the performance +of UMFPACK by up to 50\% on a Dell Latitude C840 laptop (2GHz Pentium 4M, +512K L2 cache, 1GB main memory). The peak performance of +{\tt umfpack\_di\_numeric} with Goto and van de Geijn's BLAS is 1.6 Gflops +on this computer. In MATLAB, the peak performance of UMFPACK on +a dense matrix (stored in sparse format) is 900 Mflops, as compared to +1 Gflop for {\tt x = A}$\backslash${\tt b} +when {\tt A} is stored as a regular full matrix. + +When you compile your program that uses the C-callable UMFPACK library, +you need to link your program with both libraries +({\tt UMFPACK/Lib/libumfpack.a} and {\tt AMD/Lib/libamd.a}) +and you need to tell your compiler to look in the +directories {\tt UMFPACK/Include} and {\tt AMD/Include} for include +files. See {\tt UMFPACK/Demo/Makefile} for an example. +You do not need to directly include any AMD include files in your +program, unless you directly call AMD routines. You only need the +\begin{verbatim} +#include "umfpack.h" +\end{verbatim} +statement, as described in Section~\ref{Synopsis}. + +If you would like to compile both 32-bit and 64-bit versions of the libraries, +you will need to do it in two steps. Modify your {\tt Make/Make.} +file, and select the 32-bit option. Type {\tt make} in the {\tt UMFPACK} +directory, which creates the {\tt UMFPACK/Lib/libumfpack.a} and +{\tt AMD/Lib/libamd.a} libraries. Rename those two files. Edit your +{\tt Make/Make.} and select the 64-bit option. Type {\tt make purge}, +and then {\tt make}, and you will create the 64-bit libraries. +You can use the same {\tt umfpack.h} include file for both 32-bit and +64-bit versions. Simply link your program with the appropriate 32-bit +or 64-bit compiled version of the UMFPACK and AMD libraries. + +Type {\tt make hb} in the {\tt UMFPACK/Demo/HB} directory +to compile and run a C program that reads in and factorizes +Harwell/Boeing matrices. Note that this uses a stand-alone Fortran +program to read in the Fortran-formatted Harwell/Boeing matrices and +write them to a file which can be read by a C program. + +The {\tt umf\_multicompile.c} file has been added to assist in the +compilation of UMFPACK in Microsoft Visual Studio, for Windows. + +%------------------------------------------------------------------------------- +\subsection{Installing the MATLAB interface} +%------------------------------------------------------------------------------- + +If all you want to do is use the UMFPACK mexFunction in MATLAB, you can skip +the use of the {\tt make} command described above. Simply type +{\tt umfpack\_make} in MATLAB while in the {\tt UMFPACK/MATLAB} directory. +You can also type {\tt amd\_make} in the {\tt AMD/MATLAB} directory +to compile the stand-alone AMD mexFunction (this is not required to +compile the UMFPACK mexFunction). This works on any computer with MATLAB, +including Windows. + +You will be prompted to select several configuration options, including +whether or not to use the BLAS. +MATLAB 5.3 (or earlier) does not include the BLAS, so you either have to +compile UMFPACK without the BLAS (UMFPACK will be slow), or modify your +{\tt /bin/mexopts.sh} by adding your BLAS library +to the {\tt CLIBS} string, +where {\tt } is the directory in which MATLAB is installed. + +If you are using Windows and the {\tt lcc} compiler bundled with +MATLAB 6.1, then you may need to copy the +{\tt UMFPACK}$\backslash${\tt MATLAB}$\backslash${\tt lcc\_lib}$\backslash${\tt libmwlapack.lib} +file into the +{\tt }$\backslash${\tt extern}$\backslash${\tt lib}$\backslash${\tt win32}$\backslash${\tt lcc}$\backslash$ +directory. +Next, type {\tt mex -setup} +at the MATLAB prompt, and ask MATLAB to select the {\tt lcc} compiler. +MATLAB 6.1 has built-in BLAS, but in that version of MATLAB the BLAS +cannot be accessed by a mexFunction compiled by {\tt lcc} without first copying +this file to the location listed above. +If you have MATLAB 6.5 or later, you can probably skip this step. + +%------------------------------------------------------------------------------- +\subsection{Installing the Fortran interface} +%------------------------------------------------------------------------------- + +Once the 32-bit C-callable UMFPACK library is compiled, you can also compile +the Fortran interface, by typing {\tt make fortran}. This will create +the {\tt umf4hb} program, test it, and compare the output with the +file {\tt umf4hb.out} in the distribution. +If you compiled UMFPACK in 64-bit mode, you need to use {\tt make fortran64} +instead, which compiles the {\tt umf4hb64} program and compares its output +with the file {\tt umf4hb64.out}. +Refer to the comments in the {\tt Demo/umf4\_f77wrapper.c} file +for more details. + +This interface is {\bf highly} non-portable, since it depends +on how C and Fortran are interfaced. +Because of this issue, the interface is included in the {\tt Demo} directory, +and not as a primary part of the UMFPACK library. The interface routines are +not included in the compiled {\tt UMFPACK/Lib/libumfpack.a} library, but left +as stand-alone compiled files ({\tt umf4\_f77wrapper.o} and +{\tt umf4\_f77wrapper64.o} in the {\tt Demo} directory). +You may need to modify the interface routines in the file +{\tt umf4\_f77wrapper.c} if you are using compilers for which this interface +has not been tested. + +%------------------------------------------------------------------------------- +\subsection{Known Issues} +%------------------------------------------------------------------------------- + +The Microsoft C or C++ compilers on a Pentium badly break the IEEE 754 standard, +and do not treat NaN's properly. According to IEEE 754, the expression +{\tt (x != x)} is supposed to be true if and only if {\tt x} is NaN. For +non-compliant compilers in Windows that expression is always false, and another +test must be used: {\tt (x < x)} is true if and only if {\tt x} +is NaN. For compliant compilers, {\tt (x < x)} is always false, for any +value of {\tt x} (including NaN). +To cover both cases, UMFPACK when running under Microsoft Windows +defines the following macro, which is true if and only if {\tt x} is NaN, +regardless of whether your compiler is compliant or not: + +\begin{verbatim} +#define SCALAR_IS_NAN(x) (((x) != (x)) || ((x) < (x))) +\end{verbatim} + +If your compiler breaks this test, then UMFPACK will fail catastrophically +if it encounters a NaN. You will not just see NaN's in your output; UMFPACK +will probably crash with a segmentation fault. In that case, you might try to +see if the common (but non-ANSI C) routine {\tt isnan} is available, and modify +the macro {\tt SCALAR\_IS\_NAN} in {\tt umf\_version.h} accordingly. The +simpler (and IEEE 754-compliant) test {\tt (x != x)} is always true with Linux +on a PC, and on every Unix compiler I have tested. + +Some compilers will complain about the Fortran BLAS being defined implicitly. +C prototypes for the BLAS are not used, except the C-BLAS. Some compilers +will complain about unrecognized {\tt \#pragma}'s. You may safely ignore +all of these warnings. + +%------------------------------------------------------------------------------- +\section{Future work} +\label{Future} +%------------------------------------------------------------------------------- + +Here are a few features that are not in UMFPACK Version 4.4, in no particular +order. They may appear in a future release of UMFPACK. If you are interested, +let me know and I could consider including them: + +\begin{enumerate} + +\item Future versions may have different default {\tt Control} parameters. + Future versions may return more statistics in the {\tt Info} array, and + they may use more entries in the {\tt Control} array. + These two arrays will probably become larger, since there are very few + unused entries. If they change in size, the constants + {\tt UMFPACK\_CONTROL} and {\tt UMFPACK\_INFO} defined in {\tt umfpack.h} + will be changed to reflect their new size. Your C program should use + these constants when declaring the size of these two arrays. Do not + define them as {\tt Control [20]} and {\tt Info [90]}. + +\item Forward/back solvers for the conventional row or column-form data + structure for $\m{L}$ and $\m{U}$ (the output of + {\tt umfpack\_*\_di\_get\_numeric}). This would enable a separate + solver that could be used to write a MATLAB mexFunction + {\tt x = lu\_refine (A, b, L, U, P, Q, R)} that gives MATLAB access + to the iterative refinement algorithm with sparse backward error + analysis. It would also be easier to handle sparse right-hand-sides + in this data structure, and end up with good asymptotic run-time + in this case + (particularly for $\m{Lx}=\m{b}$; see \cite{GilbertPeierls88}). + +\item Complex absolute value computations could be + based on FDLIBM (see \newline + http://www.netlib.org/fdlibm), + using the {\tt hypot(x,y)} routine. + +\item When using iterative refinement, the residual $\m{Ax}-\m{b}$ could be + returned by {\tt umfpack\_solve}. + +\item The solve routines could handle multiple right-hand sides, and sparse + right-hand sides. See {\tt umfpack\_solve} for the MATLAB version + of this feature. + +\item An option to redirect the error and diagnostic output. + +\item Permutation to block-triangular-form \cite{Duff78a} for the C-callable + interface. There are two routines in the ACM Collected + Algorithms (529 and 575) \cite{Duff81b,Duff78b} + that could be translated from Fortran + to C and included in UMFPACK. This would result in better performance + for matrices from circuit simulation and + chemical process engineering. See {\tt umfpack\_btf.m} for the MATLAB + version of this feature. An upcoming package (KLU) will include + this feature. + +\item The ability to use user-provided {\tt malloc}, {\tt free}, and + {\tt realloc} memory allocation routines. Note that UMFPACK makes very + few calls to these routines. You can do this at compile-time by + modifying the definitions of {\tt ALLOCATE}, {\tt FREE}, and + {\tt REALLOCATE} in the file {\tt umf\_internal.h}. Be sure to document + your changes carefully when you change UMFPACK source code. + +\item The ability to use user-provided work arrays, so that {\tt malloc}, + {\tt free}, and {\tt realloc} realloc are not called. The + {\tt umfpack\_*\_wsolve} routine is one example. + +\item A method that takes time proportional to the number of nonzeros in + $\m{A}$ to compute the symbolic factorization \cite{GilbertNgPeyton94}. + This would improve the performance of the symmetric and 2-by-2 strategies, + and the unsymmetric strategy when dense rows are present. + The current method takes + time proportional to the number of nonzeros in the upper bound of $\m{U}$. + The method used in UMFPACK exploits super-columns, however, so this + bound is rarely reached. + +\item Other basic sparse matrix operations, such as sparse matrix + multiplication, could be included. + +\item A more complete Fortran interface. + +\item A C++ interface. + +\item A parallel version using MPI. This would require a large amount + of effort. + +\end{enumerate} + + +%------------------------------------------------------------------------------- +\newpage +\section{The primary UMFPACK routines} +\label{Primary} +%------------------------------------------------------------------------------- + +The include files are the same for all four versions of +UMFPACK. The generic integer type is {\tt Int}, which is an {\tt int} or +{\tt long}, depending on which version of UMFPACK you are using. + +\subsection{umfpack\_*\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_numeric.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_solve} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_solve.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_free\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_free_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_free\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_free_numeric.h via sed +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\section{Alternative routines} +\label{Alternative} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_*\_defaults} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_defaults.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_qsymbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_qsymbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_wsolve} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_wsolve.h via sed +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\section{Matrix manipulation routines} +\label{Manipulate} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_*\_col\_to\_triplet} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_col_to_triplet.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_triplet\_to\_col} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_triplet_to_col.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_transpose} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_transpose.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_scale} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_scale.h via sed +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\section{Getting the contents of opaque objects} +\label{Get} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_*\_get\_lunz} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_get_lunz.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_get\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_get_numeric.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_get\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_get_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_save\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_save_numeric.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_load\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_load_numeric.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_save\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_save_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_load\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_load_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_get\_determinant} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_get_determinant.h via sed +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\section{Reporting routines} +\label{Report} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_*\_report\_status} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_status.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_control} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_control.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_info} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_info.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_matrix} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_matrix.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_numeric} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_numeric.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_perm} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_perm.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_symbolic} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_symbolic.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_triplet} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_triplet.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_*\_report\_vector} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_report_vector.h via sed +\end{verbatim} +} + +%------------------------------------------------------------------------------- +\newpage +\section{Utility routines} +\label{Utility} +%------------------------------------------------------------------------------- + +\subsection{umfpack\_timer} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_timer.h via sed +\end{verbatim} +} + +\newpage +\subsection{umfpack\_tic and umfpack\_toc} + +{\footnotesize +\begin{verbatim} +INCLUDE umfpack_tictoc.h via sed +\end{verbatim} +} + + +%------------------------------------------------------------------------------- +\newpage +% References +%------------------------------------------------------------------------------- + +\bibliographystyle{plain} +\bibliography{UserGuide} + +\end{document} diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack.h @@ -0,0 +1,374 @@ +/* ========================================================================== */ +/* === umfpack.h ============================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + This is the umfpack.h include file, and should be included in all user code + that uses UMFPACK. Do not include any of the umf_* header files in user + code. All routines in UMFPACK starting with "umfpack_" are user-callable. + All other routines are prefixed "umf_XY_", (where X is d or z, and Y is + i or l) and are not user-callable. +*/ + +#ifndef UMFPACK_H +#define UMFPACK_H + +/* -------------------------------------------------------------------------- */ +/* size of Info and Control arrays */ +/* -------------------------------------------------------------------------- */ + +/* These might be larger in future versions, since there are only 3 unused + * entries in Info, and no unused entries in Control. */ + +#define UMFPACK_INFO 90 +#define UMFPACK_CONTROL 20 + +/* -------------------------------------------------------------------------- */ +/* User-callable routines */ +/* -------------------------------------------------------------------------- */ + +/* Primary routines: */ +#include "umfpack_symbolic.h" +#include "umfpack_numeric.h" +#include "umfpack_solve.h" +#include "umfpack_free_symbolic.h" +#include "umfpack_free_numeric.h" + +/* Alternative routines: */ +#include "umfpack_defaults.h" +#include "umfpack_qsymbolic.h" +#include "umfpack_wsolve.h" + +/* Matrix manipulation routines: */ +#include "umfpack_triplet_to_col.h" +#include "umfpack_col_to_triplet.h" +#include "umfpack_transpose.h" +#include "umfpack_scale.h" + +/* Getting the contents of the Symbolic and Numeric opaque objects: */ +#include "umfpack_get_lunz.h" +#include "umfpack_get_numeric.h" +#include "umfpack_get_symbolic.h" +#include "umfpack_save_numeric.h" +#include "umfpack_load_numeric.h" +#include "umfpack_save_symbolic.h" +#include "umfpack_load_symbolic.h" +#include "umfpack_get_determinant.h" + +/* Reporting routines (the above 14 routines print nothing): */ +#include "umfpack_report_status.h" +#include "umfpack_report_info.h" +#include "umfpack_report_control.h" +#include "umfpack_report_matrix.h" +#include "umfpack_report_triplet.h" +#include "umfpack_report_vector.h" +#include "umfpack_report_symbolic.h" +#include "umfpack_report_numeric.h" +#include "umfpack_report_perm.h" + +/* Utility routines: */ +#include "umfpack_timer.h" +#include "umfpack_tictoc.h" + +/* -------------------------------------------------------------------------- */ +/* Version, copyright, and license */ +/* -------------------------------------------------------------------------- */ + +#define UMFPACK_VERSION "UMFPACK V4.4 (Jan. 28, 2005)" + +#define UMFPACK_COPYRIGHT \ +"UMFPACK: Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved.\n" + +#define UMFPACK_LICENSE_PART1 \ +"\nUMFPACK License:\n" \ +"\n" \ +" Your use or distribution of UMFPACK or any modified version of\n" \ +" UMFPACK implies that you agree to this License.\n" \ +"\n" \ +" THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY\n" \ +" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.\n" +#define UMFPACK_LICENSE_PART2 \ +"\n" \ +" Permission is hereby granted to use or copy this program, provided\n" \ +" that the Copyright, this License, and the Availability of the original\n" \ +" version is retained on all copies. User documentation of any code that\n" \ +" uses UMFPACK or any modified version of UMFPACK code must cite the\n" \ +" Copyright, this License, the Availability note, and \"Used by permission.\"\n" +#define UMFPACK_LICENSE_PART3 \ +" Permission to modify the code and to distribute modified code is granted,\n" \ +" provided the Copyright, this License, and the Availability note are\n" \ +" retained, and a notice that the code was modified is included. This\n" \ +" software was developed with support from the National Science Foundation,\n" \ +" and is provided to you free of charge.\n" \ +"\n" \ +"Availability: http://www.cise.ufl.edu/research/sparse/umfpack\n" \ +"\n" + +/* -------------------------------------------------------------------------- */ +/* contents of Info */ +/* -------------------------------------------------------------------------- */ + +/* Note that umfpack_report.m must coincide with these definitions. S is + * the submatrix of A after removing row/col singletons and empty rows/cols. */ + +/* returned by all routines that use Info: */ +#define UMFPACK_STATUS 0 /* UMFPACK_OK, or other result */ +#define UMFPACK_NROW 1 /* n_row input value */ +#define UMFPACK_NCOL 16 /* n_col input value */ +#define UMFPACK_NZ 2 /* # of entries in A */ + +/* computed in UMFPACK_*symbolic and UMFPACK_numeric: */ +#define UMFPACK_SIZE_OF_UNIT 3 /* sizeof (Unit) */ + +/* computed in UMFPACK_*symbolic: */ +#define UMFPACK_SIZE_OF_INT 4 /* sizeof (int) */ +#define UMFPACK_SIZE_OF_LONG 5 /* sizeof (long) */ +#define UMFPACK_SIZE_OF_POINTER 6 /* sizeof (void *) */ +#define UMFPACK_SIZE_OF_ENTRY 7 /* sizeof (Entry), real or complex */ +#define UMFPACK_NDENSE_ROW 8 /* number of dense rows */ +#define UMFPACK_NEMPTY_ROW 9 /* number of empty rows */ +#define UMFPACK_NDENSE_COL 10 /* number of dense rows */ +#define UMFPACK_NEMPTY_COL 11 /* number of empty rows */ +#define UMFPACK_SYMBOLIC_DEFRAG 12 /* # of memory compactions */ +#define UMFPACK_SYMBOLIC_PEAK_MEMORY 13 /* memory used by symbolic analysis */ +#define UMFPACK_SYMBOLIC_SIZE 14 /* size of Symbolic object, in Units */ +#define UMFPACK_SYMBOLIC_TIME 15 /* time (sec.) for symbolic analysis */ +#define UMFPACK_SYMBOLIC_WALLTIME 17 /* wall clock time for sym. analysis */ +#define UMFPACK_STRATEGY_USED 18 /* strategy used: sym, unsym, 2by2 */ +#define UMFPACK_ORDERING_USED 19 /* ordering used: colamd, amd, given */ +#define UMFPACK_QFIXED 31 /* whether Q is fixed or refined */ +#define UMFPACK_DIAG_PREFERRED 32 /* whether diagonal pivoting attempted*/ +#define UMFPACK_PATTERN_SYMMETRY 33 /* symmetry of pattern of S */ +#define UMFPACK_NZ_A_PLUS_AT 34 /* nnz (S+S'), excl. diagonal */ +#define UMFPACK_NZDIAG 35 /* nnz (diag (S)) */ + +/* AMD statistics, computed in UMFPACK_*symbolic: */ +#define UMFPACK_SYMMETRIC_LUNZ 36 /* nz in L+U, if AMD ordering used */ +#define UMFPACK_SYMMETRIC_FLOPS 37 /* flops for LU, if AMD ordering used */ +#define UMFPACK_SYMMETRIC_NDENSE 38 /* # of "dense" rows/cols in S+S' */ +#define UMFPACK_SYMMETRIC_DMAX 39 /* max nz in cols of L, for AMD */ + +/* statistics for 2-by-2 strategy */ +#define UMFPACK_2BY2_NWEAK 51 /* number of weak diagonal entries*/ +#define UMFPACK_2BY2_UNMATCHED 52 /* # of weak diagonals not matched*/ +#define UMFPACK_2BY2_PATTERN_SYMMETRY 53 /* symmetry of pattern of P*S */ +#define UMFPACK_2BY2_NZ_PA_PLUS_PAT 54 /* nz in PS+(PS)' */ +#define UMFPACK_2BY2_NZDIAG 55 /* nz on diagonal of PS+(PS)' */ + +/* statistcs for singleton pruning */ +#define UMFPACK_COL_SINGLETONS 56 /* # of column singletons */ +#define UMFPACK_ROW_SINGLETONS 57 /* # of row singletons */ +#define UMFPACK_N2 58 /* size of S */ +#define UMFPACK_S_SYMMETRIC 59 /* 1 if S square and symmetricly perm.*/ + +/* estimates computed in UMFPACK_*symbolic: */ +#define UMFPACK_NUMERIC_SIZE_ESTIMATE 20 /* final size of Numeric->Memory */ +#define UMFPACK_PEAK_MEMORY_ESTIMATE 21 /* for symbolic & numeric */ +#define UMFPACK_FLOPS_ESTIMATE 22 /* flop count */ +#define UMFPACK_LNZ_ESTIMATE 23 /* nz in L, incl. diagonal */ +#define UMFPACK_UNZ_ESTIMATE 24 /* nz in U, incl. diagonal */ +#define UMFPACK_VARIABLE_INIT_ESTIMATE 25 /* initial size of Numeric->Memory*/ +#define UMFPACK_VARIABLE_PEAK_ESTIMATE 26 /* peak size of Numeric->Memory */ +#define UMFPACK_VARIABLE_FINAL_ESTIMATE 27 /* final size of Numeric->Memory */ +#define UMFPACK_MAX_FRONT_SIZE_ESTIMATE 28 /* max frontal matrix size */ +#define UMFPACK_MAX_FRONT_NROWS_ESTIMATE 29 /* max # rows in any front */ +#define UMFPACK_MAX_FRONT_NCOLS_ESTIMATE 30 /* max # columns in any front */ + +/* exact values, (estimates shown above) computed in UMFPACK_numeric: */ +#define UMFPACK_NUMERIC_SIZE 40 /* final size of Numeric->Memory */ +#define UMFPACK_PEAK_MEMORY 41 /* for symbolic & numeric */ +#define UMFPACK_FLOPS 42 /* flop count */ +#define UMFPACK_LNZ 43 /* nz in L, incl. diagonal */ +#define UMFPACK_UNZ 44 /* nz in U, incl. diagonal */ +#define UMFPACK_VARIABLE_INIT 45 /* initial size of Numeric->Memory*/ +#define UMFPACK_VARIABLE_PEAK 46 /* peak size of Numeric->Memory */ +#define UMFPACK_VARIABLE_FINAL 47 /* final size of Numeric->Memory */ +#define UMFPACK_MAX_FRONT_SIZE 48 /* max frontal matrix size */ +#define UMFPACK_MAX_FRONT_NROWS 49 /* max # rows in any front */ +#define UMFPACK_MAX_FRONT_NCOLS 50 /* max # columns in any front */ + +/* computed in UMFPACK_numeric: */ +#define UMFPACK_NUMERIC_DEFRAG 60 /* # of garbage collections */ +#define UMFPACK_NUMERIC_REALLOC 61 /* # of memory reallocations */ +#define UMFPACK_NUMERIC_COSTLY_REALLOC 62 /* # of costlly memory realloc's */ +#define UMFPACK_COMPRESSED_PATTERN 63 /* # of integers in LU pattern */ +#define UMFPACK_LU_ENTRIES 64 /* # of reals in LU factors */ +#define UMFPACK_NUMERIC_TIME 65 /* numeric factorization time */ +#define UMFPACK_UDIAG_NZ 66 /* nz on diagonal of U */ +#define UMFPACK_RCOND 67 /* est. reciprocal condition # */ +#define UMFPACK_WAS_SCALED 68 /* none, max row, or sum row */ +#define UMFPACK_RSMIN 69 /* min (max row) or min (sum row) */ +#define UMFPACK_RSMAX 70 /* max (max row) or max (sum row) */ +#define UMFPACK_UMIN 71 /* min abs diagonal entry of U */ +#define UMFPACK_UMAX 72 /* max abs diagonal entry of U */ +#define UMFPACK_ALLOC_INIT_USED 73 /* alloc_init parameter used */ +#define UMFPACK_FORCED_UPDATES 74 /* # of forced updates */ +#define UMFPACK_NUMERIC_WALLTIME 75 /* numeric wall clock time */ +#define UMFPACK_NOFF_DIAG 76 /* number of off-diagonal pivots */ + +#define UMFPACK_ALL_LNZ 77 /* nz in L, if no dropped entries */ +#define UMFPACK_ALL_UNZ 78 /* nz in U, if no dropped entries */ +#define UMFPACK_NZDROPPED 79 /* # of dropped small entries */ + +/* computed in UMFPACK_solve: */ +#define UMFPACK_IR_TAKEN 80 /* # of iterative refinement steps taken */ +#define UMFPACK_IR_ATTEMPTED 81 /* # of iter. refinement steps attempted */ +#define UMFPACK_OMEGA1 82 /* omega1, sparse backward error estimate */ +#define UMFPACK_OMEGA2 83 /* omega2, sparse backward error estimate */ +#define UMFPACK_SOLVE_FLOPS 84 /* flop count for solve */ +#define UMFPACK_SOLVE_TIME 85 /* solve time (seconds) */ +#define UMFPACK_SOLVE_WALLTIME 86 /* solve time (wall clock, seconds) */ + +/* Info [87, 88, 89] unused */ + +/* Unused parts of Info may be used in future versions of UMFPACK. */ + +/* -------------------------------------------------------------------------- */ + +/* Info [UMFPACK_ORDERING_USED] is one of the following: */ +#define UMFPACK_ORDERING_COLAMD 0 /* COLAMD(A) */ +#define UMFPACK_ORDERING_AMD 1 /* AMD(A+A') */ +#define UMFPACK_ORDERING_GIVEN 2 /* Q is provided on input */ + +/* -------------------------------------------------------------------------- */ +/* contents of Control */ +/* -------------------------------------------------------------------------- */ + +/* used in all UMFPACK_report_* routines: */ +#define UMFPACK_PRL 0 /* print level */ + +/* used in UMFPACK_*symbolic only: */ +#define UMFPACK_DENSE_ROW 1 /* dense row parameter */ +#define UMFPACK_DENSE_COL 2 /* dense col parameter */ +#define UMFPACK_BLOCK_SIZE 4 /* BLAS-3 block size */ +#define UMFPACK_STRATEGY 5 /* auto, symmetric, unsym., or 2by2 */ +#define UMFPACK_2BY2_TOLERANCE 12 /* 2-by-2 pivot tolerance */ +#define UMFPACK_FIXQ 13 /* -1: no fixQ, 0: default, 1: fixQ */ +#define UMFPACK_AMD_DENSE 14 /* for AMD ordering */ +#define UMFPACK_AGGRESSIVE 19 /* whether or not to use aggressive + * absorption in AMD and COLAMD */ + +/* used in UMFPACK_numeric only: */ +#define UMFPACK_PIVOT_TOLERANCE 3 /* threshold partial pivoting setting */ +#define UMFPACK_ALLOC_INIT 6 /* initial allocation ratio */ +#define UMFPACK_SYM_PIVOT_TOLERANCE 15 /* threshold, only for diag. entries */ +#define UMFPACK_SCALE 16 /* what row scaling to do */ +#define UMFPACK_FRONT_ALLOC_INIT 17 /* frontal matrix allocation ratio */ +#define UMFPACK_DROPTOL 18 /* drop tolerance for entries in L,U */ + +/* used in UMFPACK_*solve only: */ +#define UMFPACK_IRSTEP 7 /* max # of iterative refinements */ + +/* compile-time settings - Control [8..11] cannot be changed at run time: */ +#define UMFPACK_COMPILED_WITH_BLAS 8 /* uses the BLAS */ +#define UMFPACK_COMPILED_FOR_MATLAB 9 /* 1 if MATLAB mexFunction, etc. */ +#define UMFPACK_COMPILED_WITH_GETRUSAGE 10 /* uses getrusage timer, or not */ +#define UMFPACK_COMPILED_IN_DEBUG_MODE 11 /* debugging enabled (very slow!) */ + +/* -------------------------------------------------------------------------- */ + +/* Control [UMFPACK_STRATEGY] is one of the following: */ +#define UMFPACK_STRATEGY_AUTO 0 /* use sym. or unsym. strategy */ +#define UMFPACK_STRATEGY_UNSYMMETRIC 1 /* COLAMD(A), coletree postorder, + not prefer diag*/ +#define UMFPACK_STRATEGY_2BY2 2 /* AMD(PA+PA'), no coletree postorder, + prefer diag(PA) where P is pseudo + max transversal */ +#define UMFPACK_STRATEGY_SYMMETRIC 3 /* AMD(A+A'), no coletree postorder, + prefer diagonal */ + +/* Control [UMFPACK_SCALE] is one of the following: */ +#define UMFPACK_SCALE_NONE 0 /* no scaling */ +#define UMFPACK_SCALE_SUM 1 /* default: divide each row by sum (abs (row))*/ +#define UMFPACK_SCALE_MAX 2 /* divide each row by max (abs (row)) */ + +/* -------------------------------------------------------------------------- */ +/* default values of Control: */ +/* -------------------------------------------------------------------------- */ + +#define UMFPACK_DEFAULT_PRL 1 +#define UMFPACK_DEFAULT_DENSE_ROW 0.2 +#define UMFPACK_DEFAULT_DENSE_COL 0.2 +#define UMFPACK_DEFAULT_PIVOT_TOLERANCE 0.1 +#define UMFPACK_DEFAULT_2BY2_TOLERANCE 0.01 +#define UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE 0.001 +#define UMFPACK_DEFAULT_BLOCK_SIZE 32 +#define UMFPACK_DEFAULT_ALLOC_INIT 0.7 +#define UMFPACK_DEFAULT_FRONT_ALLOC_INIT 0.5 +#define UMFPACK_DEFAULT_IRSTEP 2 +#define UMFPACK_DEFAULT_SCALE UMFPACK_SCALE_SUM +#define UMFPACK_DEFAULT_STRATEGY UMFPACK_STRATEGY_AUTO +#define UMFPACK_DEFAULT_AMD_DENSE AMD_DEFAULT_DENSE +#define UMFPACK_DEFAULT_FIXQ 0 +#define UMFPACK_DEFAULT_AGGRESSIVE 1 +#define UMFPACK_DEFAULT_DROPTOL 0 + +/* default values of Control may change in future versions of UMFPACK. */ + +/* -------------------------------------------------------------------------- */ +/* status codes */ +/* -------------------------------------------------------------------------- */ + +#define UMFPACK_OK (0) + +/* status > 0 means a warning, but the method was successful anyway. */ +/* A Symbolic or Numeric object was still created. */ +#define UMFPACK_WARNING_singular_matrix (1) + +/* The following warnings were added in umfpack_*_get_determinant */ +#define UMFPACK_WARNING_determinant_underflow (2) +#define UMFPACK_WARNING_determinant_overflow (3) + +/* status < 0 means an error, and the method was not successful. */ +/* No Symbolic of Numeric object was created. */ +#define UMFPACK_ERROR_out_of_memory (-1) +#define UMFPACK_ERROR_invalid_Numeric_object (-3) +#define UMFPACK_ERROR_invalid_Symbolic_object (-4) +#define UMFPACK_ERROR_argument_missing (-5) +#define UMFPACK_ERROR_n_nonpositive (-6) +#define UMFPACK_ERROR_invalid_matrix (-8) +#define UMFPACK_ERROR_different_pattern (-11) +#define UMFPACK_ERROR_invalid_system (-13) +#define UMFPACK_ERROR_invalid_permutation (-15) +#define UMFPACK_ERROR_internal_error (-911) /* yes, call me if you get this! */ +#define UMFPACK_ERROR_file_IO (-17) + +/* -------------------------------------------------------------------------- */ +/* solve codes */ +/* -------------------------------------------------------------------------- */ + +/* Solve the system ( )x=b, where ( ) is defined below. "t" refers to the */ +/* linear algebraic transpose (complex conjugate if A is complex), or the (') */ +/* operator in MATLAB. "at" refers to the array transpose, or the (.') */ +/* operator in MATLAB. */ + +#define UMFPACK_A (0) /* Ax=b */ +#define UMFPACK_At (1) /* A'x=b */ +#define UMFPACK_Aat (2) /* A.'x=b */ + +#define UMFPACK_Pt_L (3) /* P'Lx=b */ +#define UMFPACK_L (4) /* Lx=b */ +#define UMFPACK_Lt_P (5) /* L'Px=b */ +#define UMFPACK_Lat_P (6) /* L.'Px=b */ +#define UMFPACK_Lt (7) /* L'x=b */ +#define UMFPACK_Lat (8) /* L.'x=b */ + +#define UMFPACK_U_Qt (9) /* UQ'x=b */ +#define UMFPACK_U (10) /* Ux=b */ +#define UMFPACK_Q_Ut (11) /* QU'x=b */ +#define UMFPACK_Q_Uat (12) /* QU.'x=b */ +#define UMFPACK_Ut (13) /* U'x=b */ +#define UMFPACK_Uat (14) /* U.'x=b */ + +/* -------------------------------------------------------------------------- */ + +/* Integer constants are used for status and solve codes instead of enum */ +/* to make it easier for a Fortran code to call UMFPACK. */ + +#endif /* UMFPACK_H */ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_col_to_triplet.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_col_to_triplet.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_col_to_triplet.h @@ -0,0 +1,110 @@ +/* ========================================================================== */ +/* === umfpack_col_to_triplet =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_col_to_triplet +( + int n_col, + const int Ap [ ], + int Tj [ ] +) ; + +long umfpack_dl_col_to_triplet +( + long n_col, + const long Ap [ ], + long Tj [ ] +) ; + +int umfpack_zi_col_to_triplet +( + int n_col, + const int Ap [ ], + int Tj [ ] +) ; + +long umfpack_zl_col_to_triplet +( + long n_col, + const long Ap [ ], + long Tj [ ] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n_col, *Tj, *Ap, status ; + status = umfpack_di_col_to_triplet (n_col, Ap, Tj) ; + +double long Syntax: + + #include "umfpack.h" + long n_col, *Tj, *Ap, status ; + status = umfpack_dl_col_to_triplet (n_col, Ap, Tj) ; + +complex int Syntax: + + #include "umfpack.h" + int n_col, *Tj, *Ap, status ; + status = umfpack_zi_col_to_triplet (n_col, Ap, Tj) ; + +complex long Syntax: + + #include "umfpack.h" + long n_col, *Tj, *Ap, status ; + status = umfpack_zl_col_to_triplet (n_col, Ap, Tj) ; + +Purpose: + + Converts a column-oriented matrix to a triplet form. Only the column + pointers, Ap, are required, and only the column indices of the triplet form + are constructed. This routine is the opposite of umfpack_*_triplet_to_col. + The matrix may be singular and/or rectangular. Analogous to [i, Tj, x] = + find (A) in MATLAB, except that zero entries present in the column-form of + A are present in the output, and i and x are not created (those are just Ai + and Ax+Az*1i, respectively, for a column-form matrix A). + +Returns: + + UMFPACK_OK if successful + UMFPACK_ERROR_argument_missing if Ap or Tj is missing + UMFPACK_ERROR_n_nonpositive if n_col <= 0 + UMFPACK_ERROR_invalid_matrix if Ap [n_col] < 0, Ap [0] != 0, or + Ap [j] > Ap [j+1] for any j in the range 0 to n-1. + Unsorted columns and duplicate entries do not cause an error (these would + only be evident by examining Ai). Empty rows and columns are OK. + +Arguments: + + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. Restriction: n_col > 0. + (n_row is not required) + + Int Ap [n_col+1] ; Input argument, not modified. + + The column pointers of the column-oriented form of the matrix. See + umfpack_*_*symbolic for a description. The number of entries in + the matrix is nz = Ap [n_col]. Restrictions on Ap are the same as those + for umfpack_*_transpose. Ap [0] must be zero, nz must be >= 0, and + Ap [j] <= Ap [j+1] and Ap [j] <= Ap [n_col] must be true for all j in + the range 0 to n_col-1. Empty columns are OK (that is, Ap [j] may equal + Ap [j+1] for any j in the range 0 to n_col-1). + + Int Tj [nz] ; Output argument. + + Tj is an integer array of size nz on input, where nz = Ap [n_col]. + Suppose the column-form of the matrix is held in Ap, Ai, Ax, and Az + (see umfpack_*_*symbolic for a description). Then on output, the + triplet form of the same matrix is held in Ai (row indices), Tj (column + indices), and Ax (numerical values). Note, however, that this routine + does not require Ai and Ax (or Az for the complex version) in order to + do the conversion. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_defaults.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_defaults.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_defaults.h @@ -0,0 +1,69 @@ +/* ========================================================================== */ +/* === umfpack_defaults ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_defaults +( + double Control [UMFPACK_CONTROL] +) ; + +void umfpack_dl_defaults +( + double Control [UMFPACK_CONTROL] +) ; + +void umfpack_zi_defaults +( + double Control [UMFPACK_CONTROL] +) ; + +void umfpack_zl_defaults +( + double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_di_defaults (Control) ; + +double long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_dl_defaults (Control) ; + +complex int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_zi_defaults (Control) ; + +complex long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_zl_defaults (Control) ; + +Purpose: + + Sets the default control parameter settings. + +Arguments: + + double Control [UMFPACK_CONTROL] ; Output argument. + + Control is set to the default control parameter settings. You can + then modify individual settings by changing specific entries in the + Control array. If Control is a (double *) NULL pointer, then + umfpack_*_defaults returns silently (no error is generated, since + passing a NULL pointer for Control to any UMFPACK routine is valid). +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_numeric.h @@ -0,0 +1,67 @@ +/* ========================================================================== */ +/* === umfpack_free_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_free_numeric +( + void **Numeric +) ; + +void umfpack_dl_free_numeric +( + void **Numeric +) ; + +void umfpack_zi_free_numeric +( + void **Numeric +) ; + +void umfpack_zl_free_numeric +( + void **Numeric +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + umfpack_di_free_numeric (&Numeric) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + umfpack_dl_free_numeric (&Numeric) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + umfpack_zi_free_numeric (&Numeric) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + umfpack_zl_free_numeric (&Numeric) ; + +Purpose: + + Deallocates the Numeric object and sets the Numeric handle to NULL. This + routine is the only valid way of destroying the Numeric object. + +Arguments: + + void **Numeric ; Input argument, set to (void *) NULL on output. + + Numeric points to a valid Numeric object, computed by umfpack_*_numeric. + No action is taken if Numeric is a (void *) NULL pointer. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_free_symbolic.h @@ -0,0 +1,67 @@ +/* ========================================================================== */ +/* === umfpack_free_symbolic ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_free_symbolic +( + void **Symbolic +) ; + +void umfpack_dl_free_symbolic +( + void **Symbolic +) ; + +void umfpack_zi_free_symbolic +( + void **Symbolic +) ; + +void umfpack_zl_free_symbolic +( + void **Symbolic +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Symbolic ; + umfpack_di_free_symbolic (&Symbolic) ; + +double long Syntax: + + #include "umfpack.h" + void *Symbolic ; + umfpack_dl_free_symbolic (&Symbolic) ; + +complex int Syntax: + + #include "umfpack.h" + void *Symbolic ; + umfpack_zi_free_symbolic (&Symbolic) ; + +complex long Syntax: + + #include "umfpack.h" + void *Symbolic ; + umfpack_zl_free_symbolic (&Symbolic) ; + +Purpose: + + Deallocates the Symbolic object and sets the Symbolic handle to NULL. This + routine is the only valid way of destroying the Symbolic object. + +Arguments: + + void **Symbolic ; Input argument, set to (void *) NULL on output. + + Points to a valid Symbolic object computed by umfpack_*_symbolic. + No action is taken if Symbolic is a (void *) NULL pointer. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_determinant.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_determinant.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_determinant.h @@ -0,0 +1,192 @@ +/* ========================================================================== */ +/* === UMFPACK_get_determinant ============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_get_determinant +( + double *Mx, + double *Ex, + void *NumericHandle, + double User_Info [UMFPACK_INFO] +) ; + +long umfpack_dl_get_determinant +( + double *Mx, + double *Ex, + void *NumericHandle, + double User_Info [UMFPACK_INFO] +) ; + +int umfpack_zi_get_determinant +( + double *Mx, + double *Mz, + double *Ex, + void *NumericHandle, + double User_Info [UMFPACK_INFO] +) ; + +long umfpack_zl_get_determinant +( + double *Mx, + double *Mz, + double *Ex, + void *NumericHandle, + double User_Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status ; + double Mx, Ex, Info [UMFPACK_INFO] ; + status = umfpack_di_get_determinant (&Mx, &Ex, Numeric, Info) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status ; + double Mx, Ex, Info [UMFPACK_INFO] ; + status = umfpack_dl_get_determinant (&Mx, &Ex, Numeric, Info) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status ; + double Mx, Mz, Ex, Info [UMFPACK_INFO] ; + status = umfpack_zi_get_determinant (&Mx, &Mz, &Ex, Numeric, Info) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + long status ; + double *Mx, *Mz, *Ex, Info [UMFPACK_INFO] ; + status = umfpack_zl_get_determinant (&Mx, &Mz, &Ex, Numeric, Info) ; + +packed complex int Syntax: + + Same as above, except Mz is NULL. + +Purpose: + + Using the LU factors and the permutation vectors contained in the Numeric + object, calculate the determinant of the matrix A. + + The value of the determinant can be returned in two forms, depending on + whether Ex is NULL or not. If Ex is NULL then the value of the determinant + is returned on Mx and Mz for the real and imaginary parts. However, to + avoid over- or underflows, the determinant can be split into a mantissa + and exponent, and the parts returned separately, in which case Ex is not + NULL. The actual determinant is then given by + + double det ; + det = Mx * pow (10.0, Ex) ; + + for the double case, or + + double det [2] ; + det [0] = Mx * pow (10.0, Ex) ; // real part + det [1] = Mz * pow (10.0, Ex) ; // imaginary part + + for the complex case. Information on if the determinant will or has + over or under-flowed is given by Info [UMFPACK_STATUS]. + + In the "packed complex" syntax, Mx [0] holds the real part and Mx [1] + holds the imaginary part. Mz is not used (it is NULL). + +Returns: + + Returns UMFPACK_OK if sucessful. Returns UMFPACK_ERROR_out_of_memory if + insufficient memory is available for the n_row integer workspace that + umfpack_*_get_determinant allocates to construct pivots from the + permutation vectors. Returns UMFPACK_ERROR_invalid_Numeric_object if the + Numeric object provided as input is invalid. Returns + UMFPACK_WARNING_singular_matrix if the determinant is zero. Returns + UMFPACK_WARNING_determinant_underflow or + UMFPACK_WARNING_determinant_overflow if the determinant has underflowed + overflowed (for the case when Ex is NULL), or will overflow if Ex is not + NULL and det is computed (see above) in the user program. + +Arguments: + + double *Mx ; Output argument (array of size 1, or size 2 if Mz is NULL) + double *Mz ; Output argument (optional) + double *Ex ; Output argument (optional) + + The determinant returned in mantissa/exponent form, as discussed above. + If Mz is NULL, then both the original and imaginary parts will be + returned in Mx. If Ex is NULL then the determinant is returned directly + in Mx and Mz (or Mx [0] and Mx [1] if Mz is NULL), rather than in + mantissa/exponent form. + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric. + + double Info [UMFPACK_INFO] ; Output argument. + + Contains information about the calculation of the determinant. If a + (double *) NULL pointer is passed, then no statistics are returned in + Info (this is not an error condition). The following statistics are + computed in umfpack_*_determinant: + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + The determinant was successfully found. + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to solve the linear system. + + UMFPACK_ERROR_argument_missing + + Mx is missing (NULL). + + UMFPACK_ERROR_invalid_Numeric_object + + The Numeric object is not valid. + + UMFPACK_ERROR_invalid_system + + The matrix is rectangular. Only square systems can be + handled. + + UMFPACK_WARNING_singluar_matrix + + The determinant is zero or NaN. The matrix is singular. + + UMFPACK_WARNING_determinant_underflow + + When passing from mantissa/exponent form to the determinant + an underflow has or will occur. If the mantissa/exponent from + of obtaining the determinant is used, the underflow will occur + in the user program. If the single argument method of + obtaining the determinant is used, the underflow has already + occurred. + + UMFPACK_WARNING_determinant_overflow + + When passing from mantissa/exponent form to the determinant + an overflow has or will occur. If the mantissa/exponent from + of obtaining the determinant is used, the overflow will occur + in the user program. If the single argument method of + obtaining the determinant is used, the overflow has already + occurred. + +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_lunz.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_lunz.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_lunz.h @@ -0,0 +1,133 @@ +/* ========================================================================== */ +/* === umfpack_get_lunz ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_get_lunz +( + int *lnz, + int *unz, + int *n_row, + int *n_col, + int *nz_udiag, + void *Numeric +) ; + +long umfpack_dl_get_lunz +( + long *lnz, + long *unz, + long *n_row, + long *n_col, + long *nz_udiag, + void *Numeric +) ; + +int umfpack_zi_get_lunz +( + int *lnz, + int *unz, + int *n_row, + int *n_col, + int *nz_udiag, + void *Numeric +) ; + +long umfpack_zl_get_lunz +( + long *lnz, + long *unz, + long *n_row, + long *n_col, + long *nz_udiag, + void *Numeric +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, lnz, unz, n_row, n_col ; + status = umfpack_di_get_lunz (&lnz, &unz, &n_row, &n_col, Numeric) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, lnz, unz, n_row, n_col ; + status = umfpack_dl_get_lunz (&lnz, &unz, &n_row, &n_col, Numeric) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, lnz, unz, n_row, n_col ; + status = umfpack_zi_get_lunz (&lnz, &unz, &n_row, &n_col, Numeric) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, lnz, unz, n_row, n_col ; + status = umfpack_zl_get_lunz (&lnz, &unz, &n_row, &n_col, Numeric) ; + +Purpose: + + Determines the size and number of nonzeros in the LU factors held by the + Numeric object. These are also the sizes of the output arrays required + by umfpack_*_get_numeric. + + The matrix L is n_row -by- min(n_row,n_col), with lnz nonzeros, including + the entries on the unit diagonal of L. + + The matrix U is min(n_row,n_col) -by- n_col, with unz nonzeros, including + nonzeros on the diagonal of U. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_invalid_Numeric_object if Numeric is not a valid object. + UMFPACK_ERROR_argument_missing if any other argument is (Int *) NULL. + +Arguments: + + Int *lnz ; Output argument. + + The number of nonzeros in L, including the diagonal (which is all + one's). This value is the required size of the Lj and Lx arrays as + computed by umfpack_*_get_numeric. The value of lnz is identical to + Info [UMFPACK_LNZ], if that value was returned by umfpack_*_numeric. + + Int *unz ; Output argument. + + The number of nonzeros in U, including the diagonal. This value is the + required size of the Ui and Ux arrays as computed by + umfpack_*_get_numeric. The value of unz is identical to + Info [UMFPACK_UNZ], if that value was returned by umfpack_*_numeric. + + Int *n_row ; Output argument. + Int *n_col ; Output argument. + + The order of the L and U matrices. L is n_row -by- min(n_row,n_col) + and U is min(n_row,n_col) -by- n_col. + + Int *nz_udiag ; Output argument. + + The number of numerically nonzero values on the diagonal of U. The + matrix is singular if nz_diag < min(n_row,n_col). A divide-by-zero + will occur if nz_diag < n_row == n_col when solving a sparse system + involving the matrix U in umfpack_*_*solve. The value of nz_udiag is + identical to Info [UMFPACK_UDIAG_NZ] if that value was returned by + umfpack_*_numeric. + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_numeric.h @@ -0,0 +1,252 @@ +/* ========================================================================== */ +/* === umfpack_get_numeric ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_get_numeric +( + int Lp [ ], + int Lj [ ], + double Lx [ ], + int Up [ ], + int Ui [ ], + double Ux [ ], + int P [ ], + int Q [ ], + double Dx [ ], + int *do_recip, + double Rs [ ], + void *Numeric +) ; + +long umfpack_dl_get_numeric +( + long Lp [ ], + long Lj [ ], + double Lx [ ], + long Up [ ], + long Ui [ ], + double Ux [ ], + long P [ ], + long Q [ ], + double Dx [ ], + long *do_recip, + double Rs [ ], + void *Numeric +) ; + +int umfpack_zi_get_numeric +( + int Lp [ ], + int Lj [ ], + double Lx [ ], double Lz [ ], + int Up [ ], + int Ui [ ], + double Ux [ ], double Uz [ ], + int P [ ], + int Q [ ], + double Dx [ ], double Dz [ ], + int *do_recip, + double Rs [ ], + void *Numeric +) ; + +long umfpack_zl_get_numeric +( + long Lp [ ], + long Lj [ ], + double Lx [ ], double Lz [ ], + long Up [ ], + long Ui [ ], + double Ux [ ], double Uz [ ], + long P [ ], + long Q [ ], + double Dx [ ], double Dz [ ], + long *do_recip, + double Rs [ ], + void *Numeric +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + int *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ; + double *Lx, *Ux, *Dx, *Rs ; + status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, Dx, + &do_recip, Rs, Numeric) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + long *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ; + double *Lx, *Ux, *Dx, *Rs ; + status = umfpack_dl_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, Dx, + &do_recip, Rs, Numeric) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + int *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ; + double *Lx, *Lz, *Ux, *Uz, *Dx, *Dz, *Rs ; + status = umfpack_zi_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, P, Q, + Dx, Dz, &do_recip, Rs, Numeric) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + long *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ; + double *Lx, *Lz, *Ux, *Uz, *Dx, *Dz, *Rs ; + status = umfpack_zl_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, P, Q, + Dx, Dz, &do_recip, Rs, Numeric) ; + +packed complex int/long Syntax: + + Same as above, except Lz, Uz, and Dz are all NULL. + +Purpose: + + This routine copies the LU factors and permutation vectors from the Numeric + object into user-accessible arrays. This routine is not needed to solve a + linear system. Note that the output arrays Lp, Lj, Lx, Up, Ui, Ux, P, Q, + Dx, and Rs are not allocated by umfpack_*_get_numeric; they must exist on + input. + + All output arguments are optional. If any of them are NULL + on input, then that part of the LU factorization is not copied. You can + use this routine to extract just the parts of the LU factorization that + you want. For example, to retrieve just the column permutation Q, use: + + #define noD (double *) NULL + #define noI (int *) NULL + status = umfpack_di_get_numeric (noI, noI, noD, noI, noI, noD, noI, + Q, noD, noI, noD, Numeric) ; + +Returns: + + Returns UMFPACK_OK if successful. Returns UMFPACK_ERROR_out_of_memory + if insufficient memory is available for the 2*max(n_row,n_col) integer + workspace that umfpack_*_get_numeric allocates to construct L and/or U. + Returns UMFPACK_ERROR_invalid_Numeric_object if the Numeric object provided + as input is invalid. + +Arguments: + + Int Lp [n_row+1] ; Output argument. + Int Lj [lnz] ; Output argument. + double Lx [lnz] ; Output argument. Size 2*lnz for packed complex case. + double Lz [lnz] ; Output argument for complex versions. + + The n_row-by-min(n_row,n_col) matrix L is returned in compressed-row + form. The column indices of row i and corresponding numerical values + are in: + + Lj [Lp [i] ... Lp [i+1]-1] + Lx [Lp [i] ... Lp [i+1]-1] real part + Lz [Lp [i] ... Lp [i+1]-1] imaginary part (complex versions) + + respectively. Each row is stored in sorted order, from low column + indices to higher. The last entry in each row is the diagonal, which + is numerically equal to one. The sizes of Lp, Lj, Lx, and Lz are + returned by umfpack_*_get_lunz. If Lp, Lj, or Lx are not present, + then the matrix L is not returned. This is not an error condition. + The L matrix can be printed if n_row, Lp, Lj, Lx (and Lz for the split + complex case) are passed to umfpack_*_report_matrix (using the + "row" form). + + If Lx is present and Lz is NULL, then both real + and imaginary parts are returned in Lx[0..2*lnz-1], with Lx[2*k] + and Lx[2*k+1] being the real and imaginary part of the kth entry. + + Int Up [n_col+1] ; Output argument. + Int Ui [unz] ; Output argument. + double Ux [unz] ; Output argument. Size 2*unz for packed complex case. + double Uz [unz] ; Output argument for complex versions. + + The min(n_row,n_col)-by-n_col matrix U is returned in compressed-column + form. The row indices of column j and corresponding numerical values + are in + + Ui [Up [j] ... Up [j+1]-1] + Ux [Up [j] ... Up [j+1]-1] real part + Uz [Up [j] ... Up [j+1]-1] imaginary part (complex versions) + + respectively. Each column is stored in sorted order, from low row + indices to higher. The last entry in each column is the diagonal + (assuming that it is nonzero). The sizes of Up, Ui, Ux, and Uz are + returned by umfpack_*_get_lunz. If Up, Ui, or Ux are not present, + then the matrix U is not returned. This is not an error condition. + The U matrix can be printed if n_col, Up, Ui, Ux (and Uz for the + split complex case) are passed to umfpack_*_report_matrix (using the + "column" form). + + If Ux is present and Uz is NULL, then both real + and imaginary parts are returned in Ux[0..2*unz-1], with Ux[2*k] + and Ux[2*k+1] being the real and imaginary part of the kth entry. + + Int P [n_row] ; Output argument. + + The permutation vector P is defined as P [k] = i, where the original + row i of A is the kth pivot row in PAQ. If you do not want the P vector + to be returned, simply pass (Int *) NULL for P. This is not an error + condition. You can print P and Q with umfpack_*_report_perm. + + Int Q [n_col] ; Output argument. + + The permutation vector Q is defined as Q [k] = j, where the original + column j of A is the kth pivot column in PAQ. If you not want the Q + vector to be returned, simply pass (Int *) NULL for Q. This is not + an error condition. Note that Q is not necessarily identical to + Qtree, the column pre-ordering held in the Symbolic object. Refer to + the description of Qtree and Front_npivcol in umfpack_*_get_symbolic for + details. + + double Dx [min(n_row,n_col)] ; Output argument. Size 2*n for + the packed complex case. + double Dz [min(n_row,n_col)] ; Output argument for complex versions. + + The diagonal of U is also returned in Dx and Dz. You can extract the + diagonal of U without getting all of U by passing a non-NULL Dx (and + Dz for the complex version) and passing Up, Ui, and Ux as NULL. Dx is + the real part of the diagonal, and Dz is the imaginary part. + + If Dx is present and Dz is NULL, then both real + and imaginary parts are returned in Dx[0..2*min(n_row,n_col)-1], + with Dx[2*k] and Dx[2*k+1] being the real and imaginary part of the kth + entry. + + Int *do_recip ; Output argument. + + If do_recip is returned as zero (false), then the scale factors Rs [i] + are to be used by multiplying row i by Rs [i]. Otherwise, the entries + in row i are to be divided by Rs [i]. + + If UMFPACK has been compiled with gcc, or for MATLAB as either a + built-in routine or as a mexFunction, then the NRECIPROCAL flag is + set, and do_recip will always be zero (false). + + double Rs [n_row] ; Output argument. + + The row scale factors are returned in Rs [0..n_row-1]. Row i of A is + scaled by dividing or multiplying its values by Rs [i]. If default + scaling is in use, Rs [i] is the sum of the absolute values of row i + (or its reciprocal). If max row scaling is in use, then Rs [i] is the + maximum absolute value in row i (or its reciprocal). + Otherwise, Rs [i] = 1. If row i is all zero, Rs [i] = 1 as well. For + the complex version, an approximate absolute value is used + (|x_real|+|x_imag|). + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_get_symbolic.h @@ -0,0 +1,339 @@ +/* ========================================================================== */ +/* === umfpack_get_symbolic ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_get_symbolic +( + int *n_row, + int *n_col, + int *n1, + int *nz, + int *nfr, + int *nchains, + int P [ ], + int Q [ ], + int Front_npivcol [ ], + int Front_parent [ ], + int Front_1strow [ ], + int Front_leftmostdesc [ ], + int Chain_start [ ], + int Chain_maxrows [ ], + int Chain_maxcols [ ], + void *Symbolic +) ; + +long umfpack_dl_get_symbolic +( + long *n_row, + long *n_col, + long *n1, + long *nz, + long *nfr, + long *nchains, + long P [ ], + long Q [ ], + long Front_npivcol [ ], + long Front_parent [ ], + long Front_1strow [ ], + long Front_leftmostdesc [ ], + long Chain_start [ ], + long Chain_maxrows [ ], + long Chain_maxcols [ ], + void *Symbolic +) ; + +int umfpack_zi_get_symbolic +( + int *n_row, + int *n_col, + int *n1, + int *nz, + int *nfr, + int *nchains, + int P [ ], + int Q [ ], + int Front_npivcol [ ], + int Front_parent [ ], + int Front_1strow [ ], + int Front_leftmostdesc [ ], + int Chain_start [ ], + int Chain_maxrows [ ], + int Chain_maxcols [ ], + void *Symbolic +) ; + +long umfpack_zl_get_symbolic +( + long *n_row, + long *n_col, + long *n1, + long *nz, + long *nfr, + long *nchains, + long P [ ], + long Q [ ], + long Front_npivcol [ ], + long Front_parent [ ], + long Front_1strow [ ], + long Front_leftmostdesc [ ], + long Chain_start [ ], + long Chain_maxrows [ ], + long Chain_maxcols [ ], + void *Symbolic +) ; + +/* + +double int Syntax: + + #include "umfpack.h" + int status, n_row, n_col, nz, nfr, nchains, *P, *Q, + *Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc, + *Chain_start, *Chain_maxrows, *Chain_maxcols ; + void *Symbolic ; + status = umfpack_di_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains, + P, Q, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + +double long Syntax: + + #include "umfpack.h" + long status, n_row, n_col, nz, nfr, nchains, *P, *Q, + *Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc, + *Chain_start, *Chain_maxrows, *Chain_maxcols ; + void *Symbolic ; + status = umfpack_dl_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains, + P, Q, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + +complex int Syntax: + + #include "umfpack.h" + int status, n_row, n_col, nz, nfr, nchains, *P, *Q, + *Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc, + *Chain_start, *Chain_maxrows, *Chain_maxcols ; + void *Symbolic ; + status = umfpack_zi_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains, + P, Q, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + +complex long Syntax: + + #include "umfpack.h" + long status, n_row, n_col, nz, nfr, nchains, *P, *Q, + *Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc, + *Chain_start, *Chain_maxrows, *Chain_maxcols ; + void *Symbolic ; + status = umfpack_zl_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains, + P, Q, Front_npivcol, Front_parent, Front_1strow, + Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols, + Symbolic) ; + +Purpose: + + Copies the contents of the Symbolic object into simple integer arrays + accessible to the user. This routine is not needed to factorize and/or + solve a sparse linear system using UMFPACK. Note that the output arrays + P, Q, Front_npivcol, Front_parent, Front_1strow, Front_leftmostdesc, + Chain_start, Chain_maxrows, and Chain_maxcols are not allocated by + umfpack_*_get_symbolic; they must exist on input. + + All output arguments are optional. If any of them are NULL + on input, then that part of the symbolic analysis is not copied. You can + use this routine to extract just the parts of the symbolic analysis that + you want. For example, to retrieve just the column permutation Q, use: + + #define noI (int *) NULL + status = umfpack_di_get_symbolic (noI, noI, noI, noI, noI, noI, noI, + Q, noI, noI, noI, noI, noI, noI, noI, Symbolic) ; + + The only required argument the last one, the pointer to the Symbolic object. + + The Symbolic object is small. Its size for an n-by-n square matrix varies + from 4*n to 13*n, depending on the matrix. The object holds the initial + column permutation, the supernodal column elimination tree, and information + about each frontal matrix. You can print it with umfpack_*_report_symbolic. + +Returns: + + Returns UMFPACK_OK if successful, UMFPACK_ERROR_invalid_Symbolic_object + if Symbolic is an invalid object. + +Arguments: + + Int *n_row ; Output argument. + Int *n_col ; Output argument. + + The dimensions of the matrix A analyzed by the call to + umfpack_*_symbolic that generated the Symbolic object. + + Int *n1 ; Output argument. + + The number of pivots with zero Markowitz cost (they have just one entry + in the pivot row, or the pivot column, or both). These appear first in + the output permutations P and Q. + + Int *nz ; Output argument. + + The number of nonzeros in A. + + Int *nfr ; Output argument. + + The number of frontal matrices that will be used by umfpack_*_numeric + to factorize the matrix A. It is in the range 0 to n_col. + + Int *nchains ; Output argument. + + The frontal matrices are related to one another by the supernodal + column elimination tree. Each node in this tree is one frontal matrix. + The tree is partitioned into a set of disjoint paths, and a frontal + matrix chain is one path in this tree. Each chain is factorized using + a unifrontal technique, with a single working array that holds each + frontal matrix in the chain, one at a time. nchains is in the range + 0 to nfr. + + Int P [n_row] ; Output argument. + + The initial row permutation. If P [k] = i, then this means that + row i is the kth row in the pre-ordered matrix. In general, this P is + not the same as the final row permutation computed by umfpack_*_numeric. + + For the unsymmetric strategy, P defines the row-merge order. Let j be + the column index of the leftmost nonzero entry in row i of A*Q. Then + P defines a sort of the rows according to this value. A row can appear + earlier in this ordering if it is aggressively absorbed before it can + become a pivot row. If P [k] = i, row i typically will not be the kth + pivot row. + + For the symmetric strategy, P = Q. For the 2-by-2 strategy, P is the + row permutation that places large entries on the diagonal of P*A*Q. + If no pivoting occurs during numerical factorization, P [k] = i also + defines the final permutation of umfpack_*_numeric, for either the + symmetric or 2-by-2 strategies. + + Int Q [n_col] ; Output argument. + + The initial column permutation. If Q [k] = j, then this means that + column j is the kth pivot column in the pre-ordered matrix. Q is + not necessarily the same as the final column permutation Q, computed by + umfpack_*_numeric. The numeric factorization may reorder the pivot + columns within each frontal matrix to reduce fill-in. If the matrix is + structurally singular, and if the symmetric or 2-by-2 strategies or + used (or if Control [UMFPACK_FIXQ] > 0), then this Q will be the same + as the final column permutation computed in umfpack_*_numeric. + + Int Front_npivcol [n_col+1] ; Output argument. + + This array should be of size at least n_col+1, in order to guarantee + that it will be large enough to hold the output. Only the first nfr+1 + entries are used, however. + + The kth frontal matrix holds Front_npivcol [k] pivot columns. Thus, the + first frontal matrix, front 0, is used to factorize the first + Front_npivcol [0] columns; these correspond to the original columns + Q [0] through Q [Front_npivcol [0]-1]. The next frontal matrix + is used to factorize the next Front_npivcol [1] columns, which are thus + the original columns Q [Front_npivcol [0]] through + Q [Front_npivcol [0] + Front_npivcol [1] - 1], and so on. Columns + with no entries at all are put in a placeholder "front", + Front_npivcol [nfr]. The sum of Front_npivcol [0..nfr] is equal to + n_col. + + Any modifications that umfpack_*_numeric makes to the initial column + permutation are constrained to within each frontal matrix. Thus, for + the first frontal matrix, Q [0] through Q [Front_npivcol [0]-1] is some + permutation of the columns Q [0] through + Q [Front_npivcol [0]-1]. For second frontal matrix, + Q [Front_npivcol [0]] through Q [Front_npivcol [0] + Front_npivcol[1]-1] + is some permutation of the same portion of Q, and so on. All pivot + columns are numerically factorized within the frontal matrix originally + determined by the symbolic factorization; there is no delayed pivoting + across frontal matrices. + + Int Front_parent [n_col+1] ; Output argument. + + This array should be of size at least n_col+1, in order to guarantee + that it will be large enough to hold the output. Only the first nfr+1 + entries are used, however. + + Front_parent [0..nfr] holds the supernodal column elimination tree + (including the placeholder front nfr, which may be empty). Each node in + the tree corresponds to a single frontal matrix. The parent of node f + is Front_parent [f]. + + Int Front_1strow [n_col+1] ; Output argument. + + This array should be of size at least n_col+1, in order to guarantee + that it will be large enough to hold the output. Only the first nfr+1 + entries are used, however. + + Front_1strow [k] is the row index of the first row in A (P,Q) + whose leftmost entry is in a pivot column for the kth front. This is + necessary only to properly factorize singular matrices. Rows in the + range Front_1strow [k] to Front_1strow [k+1]-1 first become pivot row + candidates at the kth front. Any rows not eliminated in the kth front + may be selected as pivot rows in the parent of k (Front_parent [k]) + and so on up the tree. + + Int Front_leftmostdesc [n_col+1] ; Output argument. + + This array should be of size at least n_col+1, in order to guarantee + that it will be large enough to hold the output. Only the first nfr+1 + entries are used, however. + + Front_leftmostdesc [k] is the leftmost descendant of front k, or k + if the front has no children in the tree. Since the rows and columns + (P and Q) have been post-ordered via a depth-first-search of + the tree, rows in the range Front_1strow [Front_leftmostdesc [k]] to + Front_1strow [k+1]-1 form the entire set of candidate pivot rows for + the kth front (some of these will typically have already been selected + by fronts in the range Front_leftmostdesc [k] to front k-1, before + the factorization reaches front k). + + Chain_start [n_col+1] ; Output argument. + + This array should be of size at least n_col+1, in order to guarantee + that it will be large enough to hold the output. Only the first + nchains+1 entries are used, however. + + The kth frontal matrix chain consists of frontal matrices Chain_start[k] + through Chain_start [k+1]-1. Thus, Chain_start [0] is always 0, and + Chain_start [nchains] is the total number of frontal matrices, nfr. For + two adjacent fronts f and f+1 within a single chain, f+1 is always the + parent of f (that is, Front_parent [f] = f+1). + + Int Chain_maxrows [n_col+1] ; Output argument. + Int Chain_maxcols [n_col+1] ; Output argument. + + These arrays should be of size at least n_col+1, in order to guarantee + that they will be large enough to hold the output. Only the first + nchains entries are used, however. + + The kth frontal matrix chain requires a single working array of + dimension Chain_maxrows [k] by Chain_maxcols [k], for the unifrontal + technique that factorizes the frontal matrix chain. Since the symbolic + factorization only provides an upper bound on the size of each frontal + matrix, not all of the working array is necessarily used during the + numerical factorization. + + Note that the upper bound on the number of rows and columns of each + frontal matrix is computed by umfpack_*_symbolic, but all that is + required by umfpack_*_numeric is the maximum of these two sets of + values for each frontal matrix chain. Thus, the size of each + individual frontal matrix is not preserved in the Symbolic object. + + void *Symbolic ; Input argument, not modified. + + The Symbolic object, which holds the symbolic factorization computed by + umfpack_*_symbolic. The Symbolic object is not modified by + umfpack_*_get_symbolic. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_numeric.h @@ -0,0 +1,95 @@ +/* ========================================================================== */ +/* === umfpack_load_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_load_numeric +( + void **Numeric, + char *filename +) ; + +long umfpack_dl_load_numeric +( + void **Numeric, + char *filename +) ; + +int umfpack_zi_load_numeric +( + void **Numeric, + char *filename +) ; + +long umfpack_zl_load_numeric +( + void **Numeric, + char *filename +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Numeric ; + status = umfpack_di_load_numeric (&Numeric, filename) ; + +double long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Numeric ; + status = umfpack_dl_load_numeric (&Numeric, filename) ; + +complex int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Numeric ; + status = umfpack_zi_load_numeric (&Numeric, filename) ; + +complex long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Numeric ; + status = umfpack_zl_load_numeric (&Numeric, filename) ; + +Purpose: + + Loads a Numeric object from a file created by umfpack_*_save_numeric. The + Numeric handle passed to this routine is overwritten with the new object. + If that object exists prior to calling this routine, a memory leak will + occur. The contents of Numeric are ignored on input. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_out_of_memory if not enough memory is available. + UMFPACK_ERROR_file_IO if an I/O error occurred. + +Arguments: + + void **Numeric ; Output argument. + + **Numeric is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Numeric object (if successful), or (void *) NULL if + a failure occurred. + + char *filename ; Input argument, not modified. + + A string that contains the filename from which to read the Numeric + object. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_load_symbolic.h @@ -0,0 +1,95 @@ +/* ========================================================================== */ +/* === umfpack_load_symbolic ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_load_symbolic +( + void **Symbolic, + char *filename +) ; + +long umfpack_dl_load_symbolic +( + void **Symbolic, + char *filename +) ; + +int umfpack_zi_load_symbolic +( + void **Symbolic, + char *filename +) ; + +long umfpack_zl_load_symbolic +( + void **Symbolic, + char *filename +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Symbolic ; + status = umfpack_di_load_symbolic (&Symbolic, filename) ; + +double long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Symbolic ; + status = umfpack_dl_load_symbolic (&Symbolic, filename) ; + +complex int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Symbolic ; + status = umfpack_zi_load_symbolic (&Symbolic, filename) ; + +complex long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Symbolic ; + status = umfpack_zl_load_symbolic (&Symbolic, filename) ; + +Purpose: + + Loads a Symbolic object from a file created by umfpack_*_save_symbolic. The + Symbolic handle passed to this routine is overwritten with the new object. + If that object exists prior to calling this routine, a memory leak will + occur. The contents of Symbolic are ignored on input. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_out_of_memory if not enough memory is available. + UMFPACK_ERROR_file_IO if an I/O error occurred. + +Arguments: + + void **Symbolic ; Output argument. + + **Symbolic is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Symbolic object (if successful), or (void *) NULL if + a failure occurred. + + char *filename ; Input argument, not modified. + + A string that contains the filename from which to read the Symbolic + object. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_numeric.h @@ -0,0 +1,546 @@ +/* ========================================================================== */ +/* === umfpack_numeric ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_numeric +( + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + void *Symbolic, + void **Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_dl_numeric +( + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + void *Symbolic, + void **Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +int umfpack_zi_numeric +( + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + void *Symbolic, + void **Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_zl_numeric +( + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + void *Symbolic, + void **Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Symbolic, *Numeric ; + int *Ap, *Ai, status ; + double *Ax, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info); + +double long Syntax: + + #include "umfpack.h" + void *Symbolic, *Numeric ; + long *Ap, *Ai, status ; + double *Ax, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + status = umfpack_dl_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info); + +complex int Syntax: + + #include "umfpack.h" + void *Symbolic, *Numeric ; + int *Ap, *Ai, status ; + double *Ax, *Az, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + +complex long Syntax: + + #include "umfpack.h" + void *Symbolic, *Numeric ; + long *Ap, *Ai, status ; + double *Ax, *Az, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + status = umfpack_zl_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + +packed complex Syntax: + + Same as above, except that Az is NULL. + +Purpose: + + Given a sparse matrix A in column-oriented form, and a symbolic analysis + computed by umfpack_*_*symbolic, the umfpack_*_numeric routine performs the + numerical factorization, PAQ=LU, PRAQ=LU, or P(R\A)Q=LU, where P and Q are + permutation matrices (represented as permutation vectors), R is the row + scaling, L is unit-lower triangular, and U is upper triangular. This is + required before the system Ax=b (or other related linear systems) can be + solved. umfpack_*_numeric can be called multiple times for each call to + umfpack_*_*symbolic, to factorize a sequence of matrices with identical + nonzero pattern. Simply compute the Symbolic object once, with + umfpack_*_*symbolic, and reuse it for subsequent matrices. This routine + safely detects if the pattern changes, and sets an appropriate error code. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int Ap [n_col+1] ; Input argument, not modified. + + This must be identical to the Ap array passed to umfpack_*_*symbolic. + The value of n_col is what was passed to umfpack_*_*symbolic (this is + held in the Symbolic object). + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + This must be identical to the Ai array passed to umfpack_*_*symbolic. + + double Ax [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + Size 2*nz for packed complex case. + + The numerical values of the sparse matrix A. The nonzero pattern (row + indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and + the corresponding numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. + + double Az [nz] ; Input argument, not modified, for complex versions. + + For the complex versions, this holds the imaginary part of A. The + imaginary part of column j is held in Az [(Ap [j]) ... (Ap [j+1]-1)]. + + If Az is NULL, then both real + and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + void *Symbolic ; Input argument, not modified. + + The Symbolic object, which holds the symbolic factorization computed by + umfpack_*_*symbolic. The Symbolic object is not modified by + umfpack_*_numeric. + + void **Numeric ; Output argument. + + **Numeric is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Numeric object (if successful), or (void *) NULL if + a failure occurred. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PIVOT_TOLERANCE]: relative pivot tolerance for + threshold partial pivoting with row interchanges. In any given + column, an entry is numerically acceptable if its absolute value is + greater than or equal to Control [UMFPACK_PIVOT_TOLERANCE] times + the largest absolute value in the column. A value of 1.0 gives true + partial pivoting. If less than or equal to zero, then any nonzero + entry is numerically acceptable as a pivot. Default: 0.1. + + Smaller values tend to lead to sparser LU factors, but the solution + to the linear system can become inaccurate. Larger values can lead + to a more accurate solution (but not always), and usually an + increase in the total work. + + For complex matrices, a cheap approximate of the absolute value + is used for the threshold partial pivoting test (|a_real| + |a_imag| + instead of the more expensive-to-compute exact absolute value + sqrt (a_real^2 + a_imag^2)). + + Control [UMFPACK_SYM_PIVOT_TOLERANCE]: + If diagonal pivoting is attempted (the symmetric or symmetric-2by2 + strategies are used) then this parameter is used to control when the + diagonal entry is selected in a given pivot column. The absolute + value of the entry must be >= Control [UMFPACK_SYM_PIVOT_TOLERANCE] + times the largest absolute value in the column. A value of zero + will ensure that no off-diagonal pivoting is performed, except that + zero diagonal entries are not selected if there are any off-diagonal + nonzero entries. + + If an off-diagonal pivot is selected, an attempt is made to restore + symmetry later on. Suppose A (i,j) is selected, where i != j. + If column i has not yet been selected as a pivot column, then + the entry A (j,i) is redefined as a "diagonal" entry, except that + the tighter tolerance (Control [UMFPACK_PIVOT_TOLERANCE]) is + applied. This strategy has an effect similar to 2-by-2 pivoting + for symmetric indefinite matrices. If a 2-by-2 block pivot with + nonzero structure + + i j + i: 0 x + j: x 0 + + is selected in a symmetric indefinite factorization method, the + 2-by-2 block is inverted and a rank-2 update is applied. In + UMFPACK, this 2-by-2 block would be reordered as + + j i + i: x 0 + j: 0 x + + In both cases, the symmetry of the Schur complement is preserved. + + Control [UMFPACK_SCALE]: Note that the user's input matrix is + never modified, only an internal copy is scaled. + + There are three valid settings for this parameter. If any other + value is provided, the default is used. + + UMFPACK_SCALE_NONE: no scaling is performed. + + UMFPACK_SCALE_SUM: each row of the input matrix A is divided by + the sum of the absolute values of the entries in that row. + The scaled matrix has an infinity norm of 1. + + UMFPACK_SCALE_MAX: each row of the input matrix A is divided by + the maximum the absolute values of the entries in that row. + In the scaled matrix the largest entry in each row has + a magnitude exactly equal to 1. + + Note that for complex matrices, a cheap approximate absolute value + is used, |a_real| + |a_imag|, instead of the exact absolute value + sqrt ((a_real)^2 + (a_imag)^2). + + Scaling is very important for the "symmetric" strategy when + diagonal pivoting is attempted. It also improves the performance + of the "unsymmetric" strategy. + + Default: UMFPACK_SCALE_SUM. + + Control [UMFPACK_ALLOC_INIT]: + + When umfpack_*_numeric starts, it allocates memory for the Numeric + object. Part of this is of fixed size (approximately n double's + + 12*n integers). The remainder is of variable size, which grows to + hold the LU factors and the frontal matrices created during + factorization. A estimate of the upper bound is computed by + umfpack_*_*symbolic, and returned by umfpack_*_*symbolic in + Info [UMFPACK_VARIABLE_PEAK_ESTIMATE] (in Units). + + If Control [UMFPACK_ALLOC_INIT] is >= 0, umfpack_*_numeric initially + allocates space for the variable-sized part equal to this estimate + times Control [UMFPACK_ALLOC_INIT]. Typically, for matrices for + which the "unsymmetric" strategy applies, umfpack_*_numeric needs + only about half the estimated memory space, so a setting of 0.5 or + 0.6 often provides enough memory for umfpack_*_numeric to factorize + the matrix with no subsequent increases in the size of this block. + + If the matrix is ordered via AMD, then this non-negative parameter + is ignored. The initial allocation ratio computed automatically, + as 1.2 * (nz + Info [UMFPACK_SYMMETRIC_LUNZ]) / + (Info [UMFPACK_LNZ_ESTIMATE] + Info [UMFPACK_UNZ_ESTIMATE] - + min (n_row, n_col)). + + If Control [UMFPACK_ALLOC_INIT] is negative, then umfpack_*_numeric + allocates a space with initial size (in Units) equal to + (-Control [UMFPACK_ALLOC_INIT]). + + Regardless of the value of this parameter, a space equal to or + greater than the the bare minimum amount of memory needed to start + the factorization is always initially allocated. The bare initial + memory required is returned by umfpack_*_*symbolic in + Info [UMFPACK_VARIABLE_INIT_ESTIMATE] (an exact value, not an + estimate). + + If the variable-size part of the Numeric object is found to be too + small sometime after numerical factorization has started, the memory + is increased in size by a factor of 1.2. If this fails, the + request is reduced by a factor of 0.95 until it succeeds, or until + it determines that no increase in size is possible. Garbage + collection then occurs. + + The strategy of attempting to "malloc" a working space, and + re-trying with a smaller space, may not work under MATLAB, since + mxMalloc aborts the mexFunction if it fails. The built-in umfpack + routine in MATLAB 6.5 uses utMalloc instead, which + avoids this problem. As a mexFunction, utMalloc is used unless + -DNUTIL is defined at compile time. The utMalloc routine, and + utFree and utRealloc, are not documented. If the mexFunction + doesn't work, then compile it with -DNUTIL instead. + + If you are using the umfpack mexFunction, decrease the magnitude of + Control [UMFPACK_ALLOC_INIT] if you run out of memory in MATLAB. + + Default initial allocation size: 0.7. Thus, with the default + control settings and the "unsymmetric" strategy, the upper-bound is + reached after two reallocations (0.7 * 1.2 * 1.2 = 1.008). + + Changing this parameter has little effect on fill-in or operation + count. It has a small impact on run-time (the extra time required + to do the garbage collection and memory reallocation). + + Control [UMFPACK_FRONT_ALLOC_INIT]: + + When UMFPACK starts the factorization of each "chain" of frontal + matrices, it allocates a working array to hold the frontal matrices + as they are factorized. The symbolic factorization computes the + size of the largest possible frontal matrix that could occur during + the factorization of each chain. + + If Control [UMFPACK_FRONT_ALLOC_INIT] is >= 0, the following + strategy is used. If the AMD ordering was used, this non-negative + parameter is ignored. A front of size (d+2)*(d+2) is allocated, + where d = Info [UMFPACK_SYMMETRIC_DMAX]. Otherwise, a front of + size Control [UMFPACK_FRONT_ALLOC_INIT] times the largest front + possible for this chain is allocated. + + If Control [UMFPACK_FRONT_ALLOC_INIT] is negative, then a front of + size (-Control [UMFPACK_FRONT_ALLOC_INIT]) is allocated (where the + size is in terms of the number of numerical entries). This is done + regardless of the ordering method or ordering strategy used. + + Default: 0.5. + + Control [UMFPACK_DROPTOL]: + + Entries in L and U with absolute value less than or equal to the + drop tolerance are removed from the data structures (unless leaving + them there reduces memory usage by reducing the space required + for the nonzero pattern of L and U). + + Default: 0.0. + + double Info [UMFPACK_INFO] ; Output argument. + + Contains statistics about the numeric factorization. If a + (double *) NULL pointer is passed, then no statistics are returned in + Info (this is not an error condition). The following statistics are + computed in umfpack_*_numeric: + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + Numeric factorization was successful. umfpack_*_numeric + computed a valid numeric factorization. + + UMFPACK_WARNING_singular_matrix + + Numeric factorization was successful, but the matrix is + singular. umfpack_*_numeric computed a valid numeric + factorization, but you will get a divide by zero in + umfpack_*_*solve. For the other cases below, no Numeric object + is created (*Numeric is (void *) NULL). + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to complete the numeric factorization. + + UMFPACK_ERROR_argument_missing + + One or more required arguments are missing. + + UMFPACK_ERROR_invalid_Symbolic_object + + Symbolic object provided as input is invalid. + + UMFPACK_ERROR_different_pattern + + The pattern (Ap and/or Ai) has changed since the call to + umfpack_*_*symbolic which produced the Symbolic object. + + Info [UMFPACK_NROW]: the value of n_row stored in the Symbolic object. + + Info [UMFPACK_NCOL]: the value of n_col stored in the Symbolic object. + + Info [UMFPACK_NZ]: the number of entries in the input matrix. + This value is obtained from the Symbolic object. + + Info [UMFPACK_SIZE_OF_UNIT]: the number of bytes in a Unit, for memory + usage statistics below. + + Info [UMFPACK_VARIABLE_INIT]: the initial size (in Units) of the + variable-sized part of the Numeric object. If this differs from + Info [UMFPACK_VARIABLE_INIT_ESTIMATE], then the pattern (Ap and/or + Ai) has changed since the last call to umfpack_*_*symbolic, which is + an error condition. + + Info [UMFPACK_VARIABLE_PEAK]: the peak size (in Units) of the + variable-sized part of the Numeric object. This size is the amount + of space actually used inside the block of memory, not the space + allocated via UMF_malloc. You can reduce UMFPACK's memory + requirements by setting Control [UMFPACK_ALLOC_INIT] to the ratio + Info [UMFPACK_VARIABLE_PEAK] / Info[UMFPACK_VARIABLE_PEAK_ESTIMATE]. + This will ensure that no memory reallocations occur (you may want to + add 0.001 to make sure that integer roundoff does not lead to a + memory size that is 1 Unit too small; otherwise, garbage collection + and reallocation will occur). + + Info [UMFPACK_VARIABLE_FINAL]: the final size (in Units) of the + variable-sized part of the Numeric object. It holds just the + sparse LU factors. + + Info [UMFPACK_NUMERIC_SIZE]: the actual final size (in Units) of the + entire Numeric object, including the final size of the variable + part of the object. Info [UMFPACK_NUMERIC_SIZE_ESTIMATE], + an estimate, was computed by umfpack_*_*symbolic. The estimate is + normally an upper bound on the actual final size, but this is not + guaranteed. + + Info [UMFPACK_PEAK_MEMORY]: the actual peak memory usage (in Units) of + both umfpack_*_*symbolic and umfpack_*_numeric. An estimate, + Info [UMFPACK_PEAK_MEMORY_ESTIMATE], was computed by + umfpack_*_*symbolic. The estimate is normally an upper bound on the + actual peak usage, but this is not guaranteed. With testing on + hundreds of matrix arising in real applications, I have never + observed a matrix where this estimate or the Numeric size estimate + was less than the actual result, but this is theoretically possible. + Please send me one if you find such a matrix. + + Info [UMFPACK_FLOPS]: the actual count of the (useful) floating-point + operations performed. An estimate, Info [UMFPACK_FLOPS_ESTIMATE], + was computed by umfpack_*_*symbolic. The estimate is guaranteed to + be an upper bound on this flop count. The flop count excludes + "useless" flops on zero values, flops performed during the pivot + search (for tentative updates and assembly of candidate columns), + and flops performed to add frontal matrices together. + + For the real version, only (+ - * /) are counted. For the complex + version, the following counts are used: + + operation flops + c = 1/b 6 + c = a*b 6 + c -= a*b 8 + + Info [UMFPACK_LNZ]: the actual nonzero entries in final factor L, + including the diagonal. This excludes any zero entries in L, + although some of these are stored in the Numeric object. The + Info [UMFPACK_LU_ENTRIES] statistic does account for all + explicitly stored zeros, however. Info [UMFPACK_LNZ_ESTIMATE], + an estimate, was computed by umfpack_*_*symbolic. The estimate is + guaranteed to be an upper bound on Info [UMFPACK_LNZ]. + + Info [UMFPACK_UNZ]: the actual nonzero entries in final factor U, + including the diagonal. This excludes any zero entries in U, + although some of these are stored in the Numeric object. The + Info [UMFPACK_LU_ENTRIES] statistic does account for all + explicitly stored zeros, however. Info [UMFPACK_UNZ_ESTIMATE], + an estimate, was computed by umfpack_*_*symbolic. The estimate is + guaranteed to be an upper bound on Info [UMFPACK_UNZ]. + + Info [UMFPACK_NUMERIC_DEFRAG]: The number of garbage collections + performed during umfpack_*_numeric, to compact the contents of the + variable-sized workspace used by umfpack_*_numeric. No estimate was + computed by umfpack_*_*symbolic. In the current version of UMFPACK, + garbage collection is performed and then the memory is reallocated, + so this statistic is the same as Info [UMFPACK_NUMERIC_REALLOC], + below. It may differ in future releases. + + Info [UMFPACK_NUMERIC_REALLOC]: The number of times that the Numeric + object was increased in size from its initial size. A rough upper + bound on the peak size of the Numeric object was computed by + umfpack_*_*symbolic, so reallocations should be rare. However, if + umfpack_*_numeric is unable to allocate that much storage, it + reduces its request until either the allocation succeeds, or until + it gets too small to do anything with. If the memory that it + finally got was small, but usable, then the reallocation count + could be high. No estimate of this count was computed by + umfpack_*_*symbolic. + + Info [UMFPACK_NUMERIC_COSTLY_REALLOC]: The number of times that the + system realloc library routine (or mxRealloc for the mexFunction) + had to move the workspace. Realloc can sometimes increase the size + of a block of memory without moving it, which is much faster. This + statistic will always be <= Info [UMFPACK_NUMERIC_REALLOC]. If your + memory space is fragmented, then the number of "costly" realloc's + will be equal to Info [UMFPACK_NUMERIC_REALLOC]. + + Info [UMFPACK_COMPRESSED_PATTERN]: The number of integers used to + represent the pattern of L and U. + + Info [UMFPACK_LU_ENTRIES]: The total number of numerical values that + are stored for the LU factors. Some of the values may be explicitly + zero in order to save space (allowing for a smaller compressed + pattern). + + Info [UMFPACK_NUMERIC_TIME]: The CPU time taken, in seconds. + + Info [UMFPACK_RCOND]: A rough estimate of the condition number, equal + to min (abs (diag (U))) / max (abs (diag (U))), or zero if the + diagonal of U is all zero. + + Info [UMFPACK_UDIAG_NZ]: The number of numerically nonzero values on + the diagonal of U. + + Info [UMFPACK_UMIN]: the smallest absolute value on the diagonal of U. + + Info [UMFPACK_UMAX]: the smallest absolute value on the diagonal of U. + + Info [UMFPACK_MAX_FRONT_SIZE]: the size of the + largest frontal matrix (number of entries). + + Info [UMFPACK_NUMERIC_WALLTIME]: The wallclock time taken, in seconds. + + Info [UMFPACK_MAX_FRONT_NROWS]: the max number of + rows in any frontal matrix. + + Info [UMFPACK_MAX_FRONT_NCOLS]: the max number of + columns in any frontal matrix. + + Info [UMFPACK_WAS_SCALED]: the scaling used, either UMFPACK_SCALE_NONE, + UMFPACK_SCALE_SUM, or UMFPACK_SCALE_MAX. + + Info [UMFPACK_RSMIN]: if scaling is performed, the smallest scale factor + for any row (either the smallest sum of absolute entries, or the + smallest maximum of absolute entries). + + Info [UMFPACK_RSMAX]: if scaling is performed, the largest scale factor + for any row (either the largest sum of absolute entries, or the + largest maximum of absolute entries). + + Info [UMFPACK_ALLOC_INIT_USED]: the initial allocation parameter used. + + Info [UMFPACK_FORCED_UPDATES]: the number of BLAS-3 updates to the + frontal matrices that were required because the frontal matrix + grew larger than its current working array. + + Info [UMFPACK_NOFF_DIAG]: number of off-diagonal pivots selected, if the + symmetric or 2-by-2 strategies are used. + + Info [UMFPACK_NZDROPPED]: the number of entries smaller in absolute + value than Control [UMFPACK_DROPTOL] that were dropped from L and U. + Note that entries on the diagonal of U are never dropped. + + Info [UMFPACK_ALL_LNZ]: the number of entries in L, including the + diagonal, if no small entries are dropped. + + Info [UMFPACK_ALL_UNZ]: the number of entries in U, including the + diagonal, if no small entries are dropped. + + Only the above listed Info [...] entries are accessed. The remaining + entries of Info are not accessed or modified by umfpack_*_numeric. + Future versions might modify different parts of Info. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_qsymbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_qsymbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_qsymbolic.h @@ -0,0 +1,150 @@ +/* ========================================================================== */ +/* === umfpack_qsymbolic ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_qsymbolic +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + const int Qinit [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_dl_qsymbolic +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + const long Qinit [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +int umfpack_zi_qsymbolic +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + const int Qinit [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_zl_qsymbolic +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + const long Qinit [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Symbolic ; + int n_row, n_col, *Ap, *Ai, *Qinit, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ; + status = umfpack_di_qsymbolic (n_row, n_col, Ap, Ai, Ax, Qinit, + &Symbolic, Control, Info) ; + +double long Syntax: + + #include "umfpack.h" + void *Symbolic ; + long n_row, n_col, *Ap, *Ai, *Qinit, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ; + status = umfpack_dl_qsymbolic (n_row, n_col, Ap, Ai, Ax, Qinit, + &Symbolic, Control, Info) ; + +complex int Syntax: + + #include "umfpack.h" + void *Symbolic ; + int n_row, n_col, *Ap, *Ai, *Qinit, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ; + status = umfpack_zi_qsymbolic (n_row, n_col, Ap, Ai, Ax, Az, Qinit, + &Symbolic, Control, Info) ; + +complex long Syntax: + + #include "umfpack.h" + void *Symbolic ; + long n_row, n_col, *Ap, *Ai, *Qinit, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ; + status = umfpack_zl_qsymbolic (n_row, n_col, Ap, Ai, Ax, Az, Qinit, + &Symbolic, Control, Info) ; + +packed complex Syntax: + + Same as above, except Az is NULL. + +Purpose: + + Given the nonzero pattern of a sparse matrix A in column-oriented form, and + a sparsity preserving column pre-ordering Qinit, umfpack_*_qsymbolic + performs the symbolic factorization of A*Qinit (or A (:,Qinit) in MATLAB + notation). This is identical to umfpack_*_symbolic, except that neither + COLAMD nor AMD are called and the user input column order Qinit is used + instead. Note that in general, the Qinit passed to umfpack_*_qsymbolic + can differ from the final Q found in umfpack_*_numeric. The unsymmetric + strategy will perform a column etree postordering done in + umfpack_*_qsymbolic and sparsity-preserving modifications are made within + each frontal matrix during umfpack_*_numeric. The symmetric and 2-by-2 + strategies will preserve Qinit, unless the matrix is structurally singular. + + See umfpack_*_symbolic for more information. + + *** WARNING *** A poor choice of Qinit can easily cause umfpack_*_numeric + to use a huge amount of memory and do a lot of work. The "default" symbolic + analysis method is umfpack_*_symbolic, not this routine. If you use this + routine, the performance of UMFPACK is your responsibility; UMFPACK will + not try to second-guess a poor choice of Qinit. + +Returns: + + The value of Info [UMFPACK_STATUS]; see umfpack_*_symbolic. + Also returns UMFPACK_ERROR_invalid_permuation if Qinit is not a valid + permutation vector. + +Arguments: + + All arguments are the same as umfpack_*_symbolic, except for the following: + + Int Qinit [n_col] ; Input argument, not modified. + + The user's fill-reducing initial column pre-ordering. This must be a + permutation of 0..n_col-1. If Qinit [k] = j, then column j is the kth + column of the matrix A (:,Qinit) to be factorized. If Qinit is an + (Int *) NULL pointer, then COLAMD or AMD are called instead. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If Qinit is not NULL, then only two strategies are recognized: + the unsymmetric strategy and the symmetric strategy. + If Control [UMFPACK_STRATEGY] is UMFPACK_STRATEGY_SYMMETRIC, + then the symmetric strategy is used. Otherwise the unsymmetric + strategy is used. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_control.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_control.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_control.h @@ -0,0 +1,76 @@ +/* ========================================================================== */ +/* === umfpack_report_control =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_report_control +( + const double Control [UMFPACK_CONTROL] +) ; + +void umfpack_dl_report_control +( + const double Control [UMFPACK_CONTROL] +) ; + +void umfpack_zi_report_control +( + const double Control [UMFPACK_CONTROL] +) ; + +void umfpack_zl_report_control +( + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_di_report_control (Control) ; + +double long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_dl_report_control (Control) ; + +complex int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_zi_report_control (Control) ; + +double long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + umfpack_zl_report_control (Control) ; + +Purpose: + + Prints the current control settings. Note that with the default print + level, nothing is printed. Does nothing if Control is (double *) NULL. + +Arguments: + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 1 or less: no output + 2 or more: print all of Control + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_info.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_info.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_info.h @@ -0,0 +1,86 @@ +/* ========================================================================== */ +/* === umfpack_report_info ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_report_info +( + const double Control [UMFPACK_CONTROL], + const double Info [UMFPACK_INFO] +) ; + +void umfpack_dl_report_info +( + const double Control [UMFPACK_CONTROL], + const double Info [UMFPACK_INFO] +) ; + +void umfpack_zi_report_info +( + const double Control [UMFPACK_CONTROL], + const double Info [UMFPACK_INFO] +) ; + +void umfpack_zl_report_info +( + const double Control [UMFPACK_CONTROL], + const double Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + umfpack_di_report_info (Control, Info) ; + +double long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + umfpack_dl_report_info (Control, Info) ; + +complex int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + umfpack_zi_report_info (Control, Info) ; + +complex long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ; + umfpack_zl_report_info (Control, Info) ; + +Purpose: + + Reports statistics from the umfpack_*_*symbolic, umfpack_*_numeric, and + umfpack_*_*solve routines. + +Arguments: + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 0 or less: no output, even when an error occurs + 1: error messages only + 2 or more: error messages, and print all of Info + Default: 1 + + double Info [UMFPACK_INFO] ; Input argument, not modified. + + Info is an output argument of several UMFPACK routines. + The contents of Info are printed on standard output. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_matrix.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_matrix.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_matrix.h @@ -0,0 +1,203 @@ +/* ========================================================================== */ +/* === umfpack_report_matrix ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_matrix +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + int col_form, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_matrix +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + long col_form, + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_matrix +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + int col_form, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_matrix +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + long col_form, + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n_row, n_col, *Ap, *Ai, status ; + double *Ax, Control [UMFPACK_CONTROL] ; + status = umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, 1, Control) ; +or: + status = umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, 0, Control) ; + +double long Syntax: + + #include "umfpack.h" + long n_row, n_col, *Ap, *Ai, status ; + double *Ax, Control [UMFPACK_CONTROL] ; + status = umfpack_dl_report_matrix (n_row, n_col, Ap, Ai, Ax, 1, Control) ; +or: + status = umfpack_dl_report_matrix (n_row, n_col, Ap, Ai, Ax, 0, Control) ; + +complex int Syntax: + + #include "umfpack.h" + int n_row, n_col, *Ap, *Ai, status ; + double *Ax, *Az, Control [UMFPACK_CONTROL] ; + status = umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 1, + Control) ; +or: + status = umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 0, + Control) ; + +complex long Syntax: + + #include "umfpack.h" + long n_row, n_col, *Ap, *Ai, status ; + double *Ax, Control [UMFPACK_CONTROL] ; + status = umfpack_zl_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 1, + Control) ; +or: + status = umfpack_zl_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 0, + Control) ; + +packed complex Syntax: + + Same as above, except Az is NULL. + +Purpose: + + Verifies and prints a row or column-oriented sparse matrix. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked). + + Otherwise (where n is n_col for the column form and n_row for row + and let ni be n_row for the column form and n_col for row): + + UMFPACK_OK if the matrix is valid. + + UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0. + UMFPACK_ERROR_argument_missing if Ap and/or Ai are missing. + UMFPACK_ERROR_invalid_matrix if Ap [n] < 0, if Ap [0] is not zero, + if Ap [j+1] < Ap [j] for any j in the range 0 to n-1, + if any row index in Ai is not in the range 0 to ni-1, or + if the row indices in any column are not in + ascending order, or contain duplicates. + UMFPACK_ERROR_out_of_memory if out of memory. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_row matrix. Restriction: n_row > 0 and n_col > 0. + + Int Ap [n+1] ; Input argument, not modified. + + n is n_row for a row-form matrix, and n_col for a column-form matrix. + + Ap is an integer array of size n+1. If col_form is true (nonzero), + then on input, it holds the "pointers" for the column form of the + sparse matrix A. The row indices of column j of the matrix A are held + in Ai [(Ap [j]) ... (Ap [j+1]-1)]. Otherwise, Ap holds the + row pointers, and the column indices of row j of the matrix are held + in Ai [(Ap [j]) ... (Ap [j+1]-1)]. + + The first entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold + for all j in the range 0 to n-1. The value nz = Ap [n] is thus the + total number of entries in the pattern of the matrix A. + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n]. + + If col_form is true (nonzero), then the nonzero pattern (row indices) + for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)]. Row indices + must be in the range 0 to n_row-1 (the matrix is 0-based). + + Otherwise, the nonzero pattern (column indices) for row j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)]. Column indices must be in the range 0 + to n_col-1 (the matrix is 0-based). + + double Ax [nz] ; Input argument, not modified, of size nz = Ap [n]. + Size 2*nz for packed complex case. + + The numerical values of the sparse matrix A. + + If col_form is true (nonzero), then the nonzero pattern (row indices) + for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the + corresponding (real) numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary parts are stored in + Az [(Ap [j]) ... (Ap [j+1]-1)], for the complex versions + (see below if Az is NULL). + + Otherwise, the nonzero pattern (column indices) for row j + is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the corresponding + (real) numerical values are stored in Ax [(Ap [j]) ... (Ap [j+1]-1)]. + The imaginary parts are stored in Az [(Ap [j]) ... (Ap [j+1]-1)], + for the complex versions (see below if Az is NULL). + + No numerical values are printed if Ax is NULL. + + double Az [nz] ; Input argument, not modified, for complex versions. + + The imaginary values of the sparse matrix A. See the description + of Ax, above. + + If Az is NULL, then both real + and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + Int col_form ; Input argument, not modified. + + The matrix is in row-oriented form if form is col_form is false (0). + Otherwise, the matrix is in column-oriented form. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_numeric.h @@ -0,0 +1,112 @@ +/* ========================================================================== */ +/* === umfpack_report_numeric =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_numeric +( + void *Numeric, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_numeric +( + void *Numeric, + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_numeric +( + void *Numeric, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_numeric +( + void *Numeric, + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + double Control [UMFPACK_CONTROL] ; + int status ; + status = umfpack_di_report_numeric (Numeric, Control) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + double Control [UMFPACK_CONTROL] ; + long status ; + status = umfpack_dl_report_numeric (Numeric, Control) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + double Control [UMFPACK_CONTROL] ; + int status ; + status = umfpack_zi_report_numeric (Numeric, Control) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + double Control [UMFPACK_CONTROL] ; + long status ; + status = umfpack_zl_report_numeric (Numeric, Control) ; + +Purpose: + + Verifies and prints a Numeric object (the LU factorization, both its pattern + numerical values, and permutation vectors P and Q). This routine checks the + object more carefully than the computational routines. Normally, this check + is not required, since umfpack_*_numeric either returns (void *) NULL, or a + valid Numeric object. However, if you suspect that your own code has + corrupted the Numeric object (by overruning memory bounds, for example), + then this routine might be able to detect a corrupted Numeric object. Since + this is a complex object, not all such user-generated errors are guaranteed + to be caught by this routine. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked). + + Otherwise: + + UMFPACK_OK if the Numeric object is valid. + UMFPACK_ERROR_invalid_Numeric_object if the Numeric object is invalid. + UMFPACK_ERROR_out_of_memory if out of memory. + +Arguments: + + void *Numeric ; Input argument, not modified. + + The Numeric object, which holds the numeric factorization computed by + umfpack_*_numeric. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_perm.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_perm.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_perm.h @@ -0,0 +1,112 @@ +/* ========================================================================== */ +/* === umfpack_report_perm ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_perm +( + int np, + const int Perm [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_perm +( + long np, + const long Perm [ ], + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_perm +( + int np, + const int Perm [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_perm +( + long np, + const long Perm [ ], + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int np, *Perm, status ; + double Control [UMFPACK_CONTROL] ; + status = umfpack_di_report_perm (np, Perm, Control) ; + +double long Syntax: + + #include "umfpack.h" + long np, *Perm, status ; + double Control [UMFPACK_CONTROL] ; + status = umfpack_dl_report_perm (np, Perm, Control) ; + +complex int Syntax: + + #include "umfpack.h" + int np, *Perm, status ; + double Control [UMFPACK_CONTROL] ; + status = umfpack_zi_report_perm (np, Perm, Control) ; + +complex long Syntax: + + #include "umfpack.h" + long np, *Perm, status ; + double Control [UMFPACK_CONTROL] ; + status = umfpack_zl_report_perm (np, Perm, Control) ; + +Purpose: + + Verifies and prints a permutation vector. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked). + + Otherwise: + UMFPACK_OK if the permutation vector is valid (this includes that case + when Perm is (Int *) NULL, which is not an error condition). + UMFPACK_ERROR_n_nonpositive if np <= 0. + UMFPACK_ERROR_out_of_memory if out of memory. + UMFPACK_ERROR_invalid_permutation if Perm is not a valid permutation vector. + +Arguments: + + Int np ; Input argument, not modified. + + Perm is an integer vector of size np. Restriction: np > 0. + + Int Perm [np] ; Input argument, not modified. + + A permutation vector of size np. If Perm is not present (an (Int *) + NULL pointer), then it is assumed to be the identity permutation. This + is consistent with its use as an input argument to umfpack_*_qsymbolic, + and is not an error condition. If Perm is present, the entries in Perm + must range between 0 and np-1, and no duplicates may exist. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_status.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_status.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_status.h @@ -0,0 +1,90 @@ +/* ========================================================================== */ +/* === umfpack_report_status ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_di_report_status +( + const double Control [UMFPACK_CONTROL], + int status +) ; + +void umfpack_dl_report_status +( + const double Control [UMFPACK_CONTROL], + long status +) ; + +void umfpack_zi_report_status +( + const double Control [UMFPACK_CONTROL], + int status +) ; + +void umfpack_zl_report_status +( + const double Control [UMFPACK_CONTROL], + long status +) ; + +/* +double int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + int status ; + umfpack_di_report_status (Control, status) ; + +double long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + long status ; + umfpack_dl_report_status (Control, status) ; + +complex int Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + int status ; + umfpack_zi_report_status (Control, status) ; + +complex long Syntax: + + #include "umfpack.h" + double Control [UMFPACK_CONTROL] ; + long status ; + umfpack_zl_report_status (Control, status) ; + +Purpose: + + Prints the status (return value) of other umfpack_* routines. + +Arguments: + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 0 or less: no output, even when an error occurs + 1: error messages only + 2 or more: print status, whether or not an error occurred + 4 or more: also print the UMFPACK Copyright + 6 or more: also print the UMFPACK License + Default: 1 + + Int status ; Input argument, not modified. + + The return value from another umfpack_* routine. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_symbolic.h @@ -0,0 +1,111 @@ +/* ========================================================================== */ +/* === umfpack_report_symbolic ============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_symbolic +( + void *Symbolic, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_symbolic +( + void *Symbolic, + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_symbolic +( + void *Symbolic, + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_symbolic +( + void *Symbolic, + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Symbolic ; + double Control [UMFPACK_CONTROL] ; + int status ; + status = umfpack_di_report_symbolic (Symbolic, Control) ; + +double long Syntax: + + #include "umfpack.h" + void *Symbolic ; + double Control [UMFPACK_CONTROL] ; + long status ; + status = umfpack_dl_report_symbolic (Symbolic, Control) ; + +complex int Syntax: + + #include "umfpack.h" + void *Symbolic ; + double Control [UMFPACK_CONTROL] ; + int status ; + status = umfpack_zi_report_symbolic (Symbolic, Control) ; + +complex long Syntax: + + #include "umfpack.h" + void *Symbolic ; + double Control [UMFPACK_CONTROL] ; + long status ; + status = umfpack_zl_report_symbolic (Symbolic, Control) ; + +Purpose: + + Verifies and prints a Symbolic object. This routine checks the object more + carefully than the computational routines. Normally, this check is not + required, since umfpack_*_*symbolic either returns (void *) NULL, or a valid + Symbolic object. However, if you suspect that your own code has corrupted + the Symbolic object (by overruning memory bounds, for example), then this + routine might be able to detect a corrupted Symbolic object. Since this is + a complex object, not all such user-generated errors are guaranteed to be + caught by this routine. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] is <= 2 (no inputs are checked). + + Otherwise: + + UMFPACK_OK if the Symbolic object is valid. + UMFPACK_ERROR_invalid_Symbolic_object if the Symbolic object is invalid. + UMFPACK_ERROR_out_of_memory if out of memory. + +Arguments: + + void *Symbolic ; Input argument, not modified. + + The Symbolic object, which holds the symbolic factorization computed by + umfpack_*_*symbolic. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_triplet.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_triplet.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_triplet.h @@ -0,0 +1,153 @@ +/* ========================================================================== */ +/* === umfpack_report_triplet =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_triplet +( + int n_row, + int n_col, + int nz, + const int Ti [ ], + const int Tj [ ], + const double Tx [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_triplet +( + long n_row, + long n_col, + long nz, + const long Ti [ ], + const long Tj [ ], + const double Tx [ ], + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_triplet +( + int n_row, + int n_col, + int nz, + const int Ti [ ], + const int Tj [ ], + const double Tx [ ], const double Tz [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_triplet +( + long n_row, + long n_col, + long nz, + const long Ti [ ], + const long Tj [ ], + const double Tx [ ], const double Tz [ ], + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n_row, n_col, nz, *Ti, *Tj, status ; + double *Tx, Control [UMFPACK_CONTROL] ; + status = umfpack_di_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Control) ; + +double long Syntax: + + #include "umfpack.h" + long n_row, n_col, nz, *Ti, *Tj, status ; + double *Tx, Control [UMFPACK_CONTROL] ; + status = umfpack_dl_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Control) ; + +complex int Syntax: + + #include "umfpack.h" + int n_row, n_col, nz, *Ti, *Tj, status ; + double *Tx, *Tz, Control [UMFPACK_CONTROL] ; + status = umfpack_zi_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Tz, + Control) ; + +complex long Syntax: + + #include "umfpack.h" + long n_row, n_col, nz, *Ti, *Tj, status ; + double *Tx, *Tz, Control [UMFPACK_CONTROL] ; + status = umfpack_zl_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Tz, + Control) ; + +packed complex Syntax: + + Same as above, except Tz is NULL. + +Purpose: + + Verifies and prints a matrix in triplet form. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked). + + Otherwise: + + UMFPACK_OK if the Triplet matrix is OK. + UMFPACK_ERROR_argument_missing if Ti and/or Tj are missing. + UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0. + UMFPACK_ERROR_invalid_matrix if nz < 0, or + if any row or column index in Ti and/or Tj + is not in the range 0 to n_row-1 or 0 to n_col-1, respectively. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. + + Int nz ; Input argument, not modified. + + The number of entries in the triplet form of the matrix. + + Int Ti [nz] ; Input argument, not modified. + Int Tj [nz] ; Input argument, not modified. + double Tx [nz] ; Input argument, not modified. + Size 2*nz for packed complex case. + double Tz [nz] ; Input argument, not modified, for complex versions. + + Ti, Tj, Tx (and Tz for complex versions) hold the "triplet" form of a + sparse matrix. The kth nonzero entry is in row i = Ti [k], column + j = Tj [k], the real numerical value of a_ij is Tx [k], and the + imaginary part of a_ij is Tz [k] (for complex versions). The row and + column indices i and j must be in the range 0 to n_row-1 or 0 to + n_col-1, respectively. Duplicate entries may be present. The + "triplets" may be in any order. Tx and Tz are optional; if Tx is + not present ((double *) NULL), then the numerical values are + not printed. + + If Tx is present and Tz is NULL, then both real + and imaginary parts are contained in Tx[0..2*nz-1], with Tx[2*k] + and Tx[2*k+1] being the real and imaginary part of the kth entry. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_vector.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_vector.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_report_vector.h @@ -0,0 +1,133 @@ +/* ========================================================================== */ +/* === umfpack_report_vector ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_report_vector +( + int n, + const double X [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_dl_report_vector +( + long n, + const double X [ ], + const double Control [UMFPACK_CONTROL] +) ; + +int umfpack_zi_report_vector +( + int n, + const double Xx [ ], const double Xz [ ], + const double Control [UMFPACK_CONTROL] +) ; + +long umfpack_zl_report_vector +( + long n, + const double Xx [ ], const double Xz [ ], + const double Control [UMFPACK_CONTROL] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n, status ; + double *X, Control [UMFPACK_CONTROL] ; + status = umfpack_di_report_vector (n, X, Control) ; + +double long Syntax: + + #include "umfpack.h" + long n, status ; + double *X, Control [UMFPACK_CONTROL] ; + status = umfpack_dl_report_vector (n, X, Control) ; + +complex int Syntax: + + #include "umfpack.h" + int n, status ; + double *Xx, *Xz, Control [UMFPACK_CONTROL] ; + status = umfpack_zi_report_vector (n, Xx, Xz, Control) ; + +complex long Syntax: + + #include "umfpack.h" + long n, status ; + double *Xx, *Xz, Control [UMFPACK_CONTROL] ; + status = umfpack_zl_report_vector (n, Xx, Xz, Control) ; + +Purpose: + + Verifies and prints a dense vector. + +Returns: + + UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked). + + Otherwise: + + UMFPACK_OK if the vector is valid. + UMFPACK_ERROR_argument_missing if X or Xx is missing. + UMFPACK_ERROR_n_nonpositive if n <= 0. + +Arguments: + + Int n ; Input argument, not modified. + + X is a real or complex vector of size n. Restriction: n > 0. + + double X [n] ; Input argument, not modified. For real versions. + + A real vector of size n. X must not be (double *) NULL. + + double Xx [n or 2*n] ; Input argument, not modified. For complex versions. + double Xz [n or 0] ; Input argument, not modified. For complex versions. + + A complex vector of size n, in one of two storage formats. + Xx must not be (double *) NULL. + + If Xz is not (double *) NULL, then Xx [i] is the real part of X (i) and + Xz [i] is the imaginary part of X (i). Both vectors are of length n. + This is the "split" form of the complex vector X. + + If Xz is (double *) NULL, then Xx holds both real and imaginary parts, + where Xx [2*i] is the real part of X (i) and Xx [2*i+1] is the imaginary + part of X (i). Xx is of length 2*n doubles. If you have an ANSI C99 + compiler with the intrinsic double _Complex type, then Xx can be of + type double _Complex in the calling routine and typecast to (double *) + when passed to umfpack_*_report_vector (this is untested, however). + This is the "merged" form of the complex vector X. + + Note that all complex routines in UMFPACK V4.4 use this same + strategy for their complex arguments. The split format is useful for + MATLAB, which holds its real and imaginary parts in seperate arrays. + The packed format is compatible with the intrinsic double _Complex + type in ANSI C99, and is also compatible with SuperLU's method of + storing complex matrices. In Version 4.3, this routine was the only + one that allowed for packed complex arguments. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_PRL]: printing level. + + 2 or less: no output. returns silently without checking anything. + 3: fully check input, and print a short summary of its status + 4: as 3, but print first few entries of the input + 5: as 3, but print all of the input + Default: 1 +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_numeric.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_numeric.h @@ -0,0 +1,90 @@ +/* ========================================================================== */ +/* === umfpack_save_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_save_numeric +( + void *Numeric, + char *filename +) ; + +long umfpack_dl_save_numeric +( + void *Numeric, + char *filename +) ; + +int umfpack_zi_save_numeric +( + void *Numeric, + char *filename +) ; + +long umfpack_zl_save_numeric +( + void *Numeric, + char *filename +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Numeric ; + status = umfpack_di_save_numeric (Numeric, filename) ; + +double long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Numeric ; + status = umfpack_dl_save_numeric (Numeric, filename) ; + +complex int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Numeric ; + status = umfpack_zi_save_numeric (Numeric, filename) ; + +complex long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Numeric ; + status = umfpack_zl_save_numeric (Numeric, filename) ; + +Purpose: + + Saves a Numeric object to a file, which can later be read by + umfpack_*_load_numeric. The Numeric object is not modified. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_invalid_Numeric_object if Numeric is not valid. + UMFPACK_ERROR_file_IO if an I/O error occurred. + +Arguments: + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric or loaded by umfpack_*_load_numeric. + + char *filename ; Input argument, not modified. + + A string that contains the filename to which the Numeric + object is written. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_save_symbolic.h @@ -0,0 +1,90 @@ +/* ========================================================================== */ +/* === umfpack_save_symbolic================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_save_symbolic +( + void *Symbolic, + char *filename +) ; + +long umfpack_dl_save_symbolic +( + void *Symbolic, + char *filename +) ; + +int umfpack_zi_save_symbolic +( + void *Symbolic, + char *filename +) ; + +long umfpack_zl_save_symbolic +( + void *Symbolic, + char *filename +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Symbolic ; + status = umfpack_di_save_symbolic (Symbolic, filename) ; + +double long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Symbolic ; + status = umfpack_dl_save_symbolic (Symbolic, filename) ; + +complex int Syntax: + + #include "umfpack.h" + int status ; + char *filename ; + void *Symbolic ; + status = umfpack_zi_save_symbolic (Symbolic, filename) ; + +complex long Syntax: + + #include "umfpack.h" + long status ; + char *filename ; + void *Symbolic ; + status = umfpack_zl_save_symbolic (Symbolic, filename) ; + +Purpose: + + Saves a Symbolic object to a file, which can later be read by + umfpack_*_load_symbolic. The Symbolic object is not modified. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_invalid_Symbolic_object if Symbolic is not valid. + UMFPACK_ERROR_file_IO if an I/O error occurred. + +Arguments: + + void *Symbolic ; Input argument, not modified. + + Symbolic must point to a valid Symbolic object, computed by + umfpack_*_symbolic or loaded by umfpack_*_load_symbolic. + + char *filename ; Input argument, not modified. + + A string that contains the filename to which the Symbolic + object is written. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_scale.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_scale.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_scale.h @@ -0,0 +1,112 @@ +/* ========================================================================== */ +/* === umfpack_scale ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_scale +( + double X [ ], + const double B [ ], + void *Numeric +) ; + +long umfpack_dl_scale +( + double X [ ], + const double B [ ], + void *Numeric +) ; + +int umfpack_zi_scale +( + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric +) ; + +long umfpack_zl_scale +( + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + double *B, *X ; + status = umfpack_di_scale (X, B, Numeric) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + double *B, *X ; + status = umfpack_dl_scale (X, B, Numeric) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + double *Bx, *Bz, *Xx, *Xz ; + status = umfpack_zi_scale (Xx, Xz, Bx, Bz, Numeric) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + double *Bx, *Bz, *Xx, *Xz ; + status = umfpack_zl_scale (Xx, Xz, Bx, Bz, Numeric) ; + +packed complex Syntax: + + Same as above, except both Xz and Bz are NULL. + +Purpose: + + Given LU factors computed by umfpack_*_numeric (PAQ=LU, PRAQ=LU, or + P(R\A)Q=LU), and a vector B, this routine computes X = B, X = R*B, or + X = R\B, as appropriate. X and B must be vectors equal in length to the + number of rows of A. + +Returns: + + The status code is returned. UMFPACK_OK is returned if successful. + UMFPACK_ERROR_invalid_Numeric_object is returned in the Numeric + object is invalid. UMFPACK_ERROR_argument_missing is returned if + any of the input vectors are missing (X and B for the real version, + and Xx and Bx for the complex version). + +Arguments: + + double X [n_row] ; Output argument. + or: + double Xx [n_row] ; Output argument, real part. + Size 2*n_row for packed complex case. + double Xz [n_row] ; Output argument, imaginary part. + + The output vector X. If either Xz or Bz are NULL, the vector + X is in packed complex form, with the kth entry in Xx [2*k] and + Xx [2*k+1], and likewise for B. + + double B [n_row] ; Input argument, not modified. + or: + double Bx [n_row] ; Input argument, not modified, real part. + Size 2*n_row for packed complex case. + double Bz [n_row] ; Input argument, not modified, imaginary part. + + The input vector B. See above if either Xz or Bz are NULL. + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric. + +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_solve.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_solve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_solve.h @@ -0,0 +1,301 @@ +/* ========================================================================== */ +/* === umfpack_solve ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_solve +( + int sys, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + double X [ ], + const double B [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_dl_solve +( + long sys, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + double X [ ], + const double B [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +int umfpack_zi_solve +( + int sys, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_zl_solve +( + long sys, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, *Ap, *Ai, sys ; + double *B, *X, *Ax, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, *Ap, *Ai, sys ; + double *B, *X, *Ax, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_dl_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, *Ap, *Ai, sys ; + double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, Info [UMFPACK_INFO], + Control [UMFPACK_CONTROL] ; + status = umfpack_zi_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, + Control, Info) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, *Ap, *Ai, sys ; + double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, Info [UMFPACK_INFO], + Control [UMFPACK_CONTROL] ; + status = umfpack_zl_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, + Control, Info) ; + +packed complex Syntax: + + Same as above, Xz, Bz, and Az are NULL. + +Purpose: + + Given LU factors computed by umfpack_*_numeric (PAQ=LU, PRAQ=LU, or + P(R\A)Q=LU) and the right-hand-side, B, solve a linear system for the + solution X. Iterative refinement is optionally performed. Only square + systems are handled. Singular matrices result in a divide-by-zero for all + systems except those involving just the matrix L. Iterative refinement is + not performed for singular matrices. In the discussion below, n is equal + to n_row and n_col, because only square systems are handled. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int sys ; Input argument, not modified. + + Defines which system to solve. (') is the linear algebraic transpose + (complex conjugate if A is complex), and (.') is the array transpose. + + sys value system solved + UMFPACK_A Ax=b + UMFPACK_At A'x=b + UMFPACK_Aat A.'x=b + UMFPACK_Pt_L P'Lx=b + UMFPACK_L Lx=b + UMFPACK_Lt_P L'Px=b + UMFPACK_Lat_P L.'Px=b + UMFPACK_Lt L'x=b + UMFPACK_U_Qt UQ'x=b + UMFPACK_U Ux=b + UMFPACK_Q_Ut QU'x=b + UMFPACK_Q_Uat QU.'x=b + UMFPACK_Ut U'x=b + UMFPACK_Uat U.'x=b + + Iterative refinement can be optionally performed when sys is any of + the following: + + UMFPACK_A Ax=b + UMFPACK_At A'x=b + UMFPACK_Aat A.'x=b + + For the other values of the sys argument, iterative refinement is not + performed (Control [UMFPACK_IRSTEP], Ap, Ai, Ax, and Az are ignored). + + Int Ap [n+1] ; Input argument, not modified. + Int Ai [nz] ; Input argument, not modified. + double Ax [nz] ; Input argument, not modified. + Size 2*nz for packed complex case. + double Az [nz] ; Input argument, not modified, for complex versions. + + If iterative refinement is requested (Control [UMFPACK_IRSTEP] >= 1, + Ax=b, A'x=b, or A.'x=b is being solved, and A is nonsingular), then + these arrays must be identical to the same ones passed to + umfpack_*_numeric. The umfpack_*_solve routine does not check the + contents of these arguments, so the results are undefined if Ap, Ai, Ax, + and/or Az are modified between the calls the umfpack_*_numeric and + umfpack_*_solve. These three arrays do not need to be present (NULL + pointers can be passed) if Control [UMFPACK_IRSTEP] is zero, or if a + system other than Ax=b, A'x=b, or A.'x=b is being solved, or if A is + singular, since in each of these cases A is not accessed. + + If Az, Xz, or Bz are NULL, then both real + and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + double X [n] ; Output argument. + or: + double Xx [n] ; Output argument, real part + Size 2*n for packed complex case. + double Xz [n] ; Output argument, imaginary part. + + The solution to the linear system, where n = n_row = n_col is the + dimension of the matrices A, L, and U. + + If Az, Xz, or Bz are NULL, then both real + and imaginary parts are returned in Xx[0..2*n-1], with Xx[2*k] and + Xx[2*k+1] being the real and imaginary part of the kth entry. + + double B [n] ; Input argument, not modified. + or: + double Bx [n] ; Input argument, not modified, real part. + Size 2*n for packed complex case. + double Bz [n] ; Input argument, not modified, imaginary part. + + The right-hand side vector, b, stored as a conventional array of size n + (or two arrays of size n for complex versions). This routine does not + solve for multiple right-hand-sides, nor does it allow b to be stored in + a sparse-column form. + + If Az, Xz, or Bz are NULL, then both real + and imaginary parts are contained in Bx[0..2*n-1], with Bx[2*k] + and Bx[2*k+1] being the real and imaginary part of the kth entry. + + void *Numeric ; Input argument, not modified. + + Numeric must point to a valid Numeric object, computed by + umfpack_*_numeric. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used. Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_IRSTEP]: The maximum number of iterative refinement + steps to attempt. A value less than zero is treated as zero. If + less than 1, or if Ax=b, A'x=b, or A.'x=b is not being solved, or + if A is singular, then the Ap, Ai, Ax, and Az arguments are not + accessed. Default: 2. + + double Info [UMFPACK_INFO] ; Output argument. + + Contains statistics about the solution factorization. If a + (double *) NULL pointer is passed, then no statistics are returned in + Info (this is not an error condition). The following statistics are + computed in umfpack_*_solve: + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + The linear system was successfully solved. + + UMFPACK_WARNING_singular_matrix + + A divide-by-zero occurred. Your solution will contain Inf's + and/or NaN's. Some parts of the solution may be valid. For + example, solving Ax=b with + + A = [2 0] b = [ 1 ] returns x = [ 0.5 ] + [0 0] [ 0 ] [ Inf ] + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to solve the linear system. + + UMFPACK_ERROR_argument_missing + + One or more required arguments are missing. The B, X, (or + Bx and Xx for the complex versions) arguments + are always required. Info and Control are not required. Ap, + Ai, Ax are required if Ax=b, + A'x=b, A.'x=b is to be solved, the (default) iterative + refinement is requested, and the matrix A is nonsingular. + + UMFPACK_ERROR_invalid_system + + The sys argument is not valid, or the matrix A is not square. + + UMFPACK_ERROR_invalid_Numeric_object + + The Numeric object is not valid. + + Info [UMFPACK_NROW], Info [UMFPACK_NCOL]: + The dimensions of the matrix A (L is n_row-by-n_inner and + U is n_inner-by-n_col, with n_inner = min(n_row,n_col)). + + Info [UMFPACK_NZ]: the number of entries in the input matrix, Ap [n], + if iterative refinement is requested (Ax=b, A'x=b, or A.'x=b is + being solved, Control [UMFPACK_IRSTEP] >= 1, and A is nonsingular). + + Info [UMFPACK_IR_TAKEN]: The number of iterative refinement steps + effectively taken. The number of steps attempted may be one more + than this; the refinement algorithm backtracks if the last + refinement step worsens the solution. + + Info [UMFPACK_IR_ATTEMPTED]: The number of iterative refinement steps + attempted. The number of times a linear system was solved is one + more than this (once for the initial Ax=b, and once for each Ay=r + solved for each iterative refinement step attempted). + + Info [UMFPACK_OMEGA1]: sparse backward error estimate, omega1, if + iterative refinement was performed, or -1 if iterative refinement + not performed. + + Info [UMFPACK_OMEGA2]: sparse backward error estimate, omega2, if + iterative refinement was performed, or -1 if iterative refinement + not performed. + + Info [UMFPACK_SOLVE_FLOPS]: the number of floating point operations + performed to solve the linear system. This includes the work + taken for all iterative refinement steps, including the backtrack + (if any). + + Info [UMFPACK_SOLVE_TIME]: The time taken, in seconds. + + Info [UMFPACK_SOLVE_WALLTIME]: The wallclock time taken, in seconds. + + Only the above listed Info [...] entries are accessed. The remaining + entries of Info are not accessed or modified by umfpack_*_solve. + Future versions might modify different parts of Info. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_symbolic.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_symbolic.h @@ -0,0 +1,536 @@ +/* ========================================================================== */ +/* === umfpack_symbolic ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_symbolic +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_dl_symbolic +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +int umfpack_zi_symbolic +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +long umfpack_zl_symbolic +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + void **Symbolic, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Symbolic ; + int n_row, n_col, *Ap, *Ai, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ; + status = umfpack_di_symbolic (n_row, n_col, Ap, Ai, Ax, + &Symbolic, Control, Info) ; + +double long Syntax: + + #include "umfpack.h" + void *Symbolic ; + long n_row, n_col, *Ap, *Ai, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ; + status = umfpack_dl_symbolic (n_row, n_col, Ap, Ai, Ax, + &Symbolic, Control, Info) ; + +complex int Syntax: + + #include "umfpack.h" + void *Symbolic ; + int n_row, n_col, *Ap, *Ai, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ; + status = umfpack_zi_symbolic (n_row, n_col, Ap, Ai, Ax, Az, + &Symbolic, Control, Info) ; + +complex long Syntax: + + #include "umfpack.h" + void *Symbolic ; + long n_row, n_col, *Ap, *Ai, status ; + double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ; + status = umfpack_zl_symbolic (n_row, n_col, Ap, Ai, Ax, Az, + &Symbolic, Control, Info) ; + +packed complex Syntax: + + Same as above, except Az is NULL. + +Purpose: + + Given nonzero pattern of a sparse matrix A in column-oriented form, + umfpack_*_symbolic performs a column pre-ordering to reduce fill-in + (using COLAMD or AMD) and a symbolic factorization. This is required + before the matrix can be numerically factorized with umfpack_*_numeric. + If you wish to bypass the COLAMD or AMD pre-ordering and provide your own + ordering, use umfpack_*_qsymbolic instead. + + Since umfpack_*_symbolic and umfpack_*_qsymbolic are very similar, options + for both routines are discussed below. + + For the following discussion, let S be the submatrix of A obtained after + eliminating all pivots of zero Markowitz cost. S has dimension + (n_row-n1-nempty_row) -by- (n_col-n1-nempty_col), where + n1 = Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS], + nempty_row = Info [UMFPACK_NEMPTY_ROW] and + nempty_col = Info [UMFPACK_NEMPTY_COL]. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0. + + Int Ap [n_col+1] ; Input argument, not modified. + + Ap is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the sparse matrix A. Column j of + the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)]. The first + entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold for all + j in the range 0 to n_col-1. The value nz = Ap [n_col] is thus the + total number of entries in the pattern of the matrix A. nz must be + greater than or equal to zero. + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + The nonzero pattern (row indices) for column j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j + must be in ascending order, and no duplicate row indices may be present. + Row indices must be in the range 0 to n_row-1 (the matrix is 0-based). + See umfpack_*_triplet_to_col for how to sort the columns of a matrix + and sum up the duplicate entries. See umfpack_*_report_matrix for how + to print the matrix A. + + double Ax [nz] ; Optional input argument, not modified. + Size 2*nz for packed complex case. + + The numerical values of the sparse matrix A. The nonzero pattern (row + indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and + the corresponding numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. Used only by the 2-by-2 strategy to + determine whether entries are "large" or "small". You do not have to + pass the same numerical values to umfpack_*_numeric. If Ax is not + present (a (double *) NULL pointer), then any entry in A is assumed to + be "large". + + double Az [nz] ; Optional input argument, not modified, for complex + versions. + + For the complex versions, this holds the imaginary part of A. The + imaginary part of column j is held in Az [(Ap [j]) ... (Ap [j+1]-1)]. + + If Az is NULL, then both real + and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + Used by the 2-by-2 strategy only. See the description of Ax, above. + + void **Symbolic ; Output argument. + + **Symbolic is the address of a (void *) pointer variable in the user's + calling routine (see Syntax, above). On input, the contents of this + variable are not defined. On output, this variable holds a (void *) + pointer to the Symbolic object (if successful), or (void *) NULL if + a failure occurred. + + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + + If a (double *) NULL pointer is passed, then the default control + settings are used (the defaults are suitable for all matrices, + ranging from those with highly unsymmetric nonzero pattern, to + symmetric matrices). Otherwise, the settings are determined from the + Control array. See umfpack_*_defaults on how to fill the Control + array with the default settings. If Control contains NaN's, the + defaults are used. The following Control parameters are used: + + Control [UMFPACK_STRATEGY]: This is the most important control + parameter. It determines what kind of ordering and pivoting + strategy that UMFPACK should use. There are 4 options: + + UMFPACK_STRATEGY_AUTO: This is the default. The input matrix is + analyzed to determine how symmetric the nonzero pattern is, and + how many entries there are on the diagonal. It then selects one + of the following strategies. Refer to the User Guide for a + description of how the strategy is automatically selected. + + UMFPACK_STRATEGY_UNSYMMETRIC: Use the unsymmetric strategy. COLAMD + is used to order the columns of A, followed by a postorder of + the column elimination tree. No attempt is made to perform + diagonal pivoting. The column ordering is refined during + factorization. + + In the numerical factorization, the + Control [UMFPACK_SYM_PIVOT_TOLERANCE] parameter is ignored. A + pivot is selected if its magnitude is >= + Control [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the + largest entry in its column. + + UMFPACK_STRATEGY_SYMMETRIC: Use the symmetric strategy + In this method, the approximate minimum degree + ordering (AMD) is applied to A+A', followed by a postorder of + the elimination tree of A+A'. UMFPACK attempts to perform + diagonal pivoting during numerical factorization. No refinement + of the column pre-ordering is performed during factorization. + + In the numerical factorization, a nonzero entry on the diagonal + is selected as the pivot if its magnitude is >= Control + [UMFPACK_SYM_PIVOT_TOLERANCE] (default 0.001) times the largest + entry in its column. If this is not acceptable, then an + off-diagonal pivot is selected with magnitude >= Control + [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry + in its column. + + UMFPACK_STRATEGY_2BY2: a row permutation P2 is found that places + large entries on the diagonal. The matrix P2*A is then + factorized using the symmetric strategy, described above. + Refer to the User Guide for more information. + + Control [UMFPACK_DENSE_COL]: + If COLAMD is used, columns with more than + max (16, Control [UMFPACK_DENSE_COL] * 16 * sqrt (n_row)) entries + are placed placed last in the column pre-ordering. Default: 0.2. + + Control [UMFPACK_DENSE_ROW]: + Rows with more than max (16, Control [UMFPACK_DENSE_ROW] * 16 * + sqrt (n_col)) entries are treated differently in the COLAMD + pre-ordering, and in the internal data structures during the + subsequent numeric factorization. Default: 0.2. + + Control [UMFPACK_AMD_DENSE]: rows/columns in A+A' with more than + max (16, Control [UMFPACK_AMD_DENSE] * sqrt (n)) entries + (where n = n_row = n_col) are ignored in the AMD pre-ordering. + Default: 10. + + Control [UMFPACK_BLOCK_SIZE]: the block size to use for Level-3 BLAS + in the subsequent numerical factorization (umfpack_*_numeric). + A value less than 1 is treated as 1. Default: 32. Modifying this + parameter affects when updates are applied to the working frontal + matrix, and can indirectly affect fill-in and operation count. + As long as the block size is large enough (8 or so), this parameter + has a modest effect on performance. + + Control [UMFPACK_2BY2_TOLERANCE]: a diagonal entry S (k,k) is + considered "small" if it is < tol * max (abs (S (:,k))), where S a + submatrix of the scaled input matrix, with pivots of zero Markowitz + cost removed. + + Control [UMFPACK_SCALE]: See umfpack_numeric.h for a description. + Only affects the 2-by-2 strategy. Default: UMFPACK_SCALE_SUM. + + Control [UMFPACK_FIXQ]: If > 0, then the pre-ordering Q is not modified + during numeric factorization. If < 0, then Q may be modified. If + zero, then this is controlled automatically (the unsymmetric + strategy modifies Q, the others do not). Default: 0. + + Control [UMFPACK_AGGRESSIVE]: If nonzero, aggressive absorption is used + in COLAMD and AMD. Default: 1. + + double Info [UMFPACK_INFO] ; Output argument, not defined on input. + + Contains statistics about the symbolic analysis. If a (double *) NULL + pointer is passed, then no statistics are returned in Info (this is not + an error condition). The entire Info array is cleared (all entries set + to -1) and then the following statistics are computed: + + Info [UMFPACK_STATUS]: status code. This is also the return value, + whether or not Info is present. + + UMFPACK_OK + + Each column of the input matrix contained row indices + in increasing order, with no duplicates. Only in this case + does umfpack_*_symbolic compute a valid symbolic factorization. + For the other cases below, no Symbolic object is created + (*Symbolic is (void *) NULL). + + UMFPACK_ERROR_n_nonpositive + + n is less than or equal to zero. + + UMFPACK_ERROR_invalid_matrix + + Number of entries in the matrix is negative, Ap [0] is nonzero, + a column has a negative number of entries, a row index is out of + bounds, or the columns of input matrix were jumbled (unsorted + columns or duplicate entries). + + UMFPACK_ERROR_out_of_memory + + Insufficient memory to perform the symbolic analysis. If the + analysis requires more than 2GB of memory and you are using + the 32-bit ("int") version of UMFPACK, then you are guaranteed + to run out of memory. Try using the 64-bit version of UMFPACK. + + UMFPACK_ERROR_argument_missing + + One or more required arguments is missing. + + UMFPACK_ERROR_internal_error + + Something very serious went wrong. This is a bug. + Please contact the author (davis@cise.ufl.edu). + + Info [UMFPACK_NROW]: the value of the input argument n_row. + + Info [UMFPACK_NCOL]: the value of the input argument n_col. + + Info [UMFPACK_NZ]: the number of entries in the input matrix + (Ap [n_col]). + + Info [UMFPACK_SIZE_OF_UNIT]: the number of bytes in a Unit, + for memory usage statistics below. + + Info [UMFPACK_SIZE_OF_INT]: the number of bytes in an int. + + Info [UMFPACK_SIZE_OF_LONG]: the number of bytes in a long. + + Info [UMFPACK_SIZE_OF_POINTER]: the number of bytes in a void * + pointer. + + Info [UMFPACK_SIZE_OF_ENTRY]: the number of bytes in a numerical entry. + + Info [UMFPACK_NDENSE_ROW]: number of "dense" rows in A. These rows are + ignored when the column pre-ordering is computed in COLAMD. They + are also treated differently during numeric factorization. If > 0, + then the matrix had to be re-analyzed by UMF_analyze, which does + not ignore these rows. + + Info [UMFPACK_NEMPTY_ROW]: number of "empty" rows in A, as determined + These are rows that either have no entries, or whose entries are + all in pivot columns of zero-Markowitz-cost pivots. + + Info [UMFPACK_NDENSE_COL]: number of "dense" columns in A. COLAMD + orders these columns are ordered last in the factorization, but + before "empty" columns. + + Info [UMFPACK_NEMPTY_COL]: number of "empty" columns in A. These are + columns that either have no entries, or whose entries are all in + pivot rows of zero-Markowitz-cost pivots. These columns are + ordered last in the factorization, to the right of "dense" columns. + + Info [UMFPACK_SYMBOLIC_DEFRAG]: number of garbage collections + performed during ordering and symbolic pre-analysis. + + Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]: the amount of memory (in Units) + required for umfpack_*_symbolic to complete. This count includes + the size of the Symbolic object itself, which is also reported in + Info [UMFPACK_SYMBOLIC_SIZE]. + + Info [UMFPACK_SYMBOLIC_SIZE]: the final size of the Symbolic object (in + Units). This is fairly small, roughly 2*n to 13*n integers, + depending on the matrix. + + Info [UMFPACK_VARIABLE_INIT_ESTIMATE]: the Numeric object contains two + parts. The first is fixed in size (O (n_row+n_col)). The + second part holds the sparse LU factors and the contribution blocks + from factorized frontal matrices. This part changes in size during + factorization. Info [UMFPACK_VARIABLE_INIT_ESTIMATE] is the exact + size (in Units) required for this second variable-sized part in + order for the numerical factorization to start. + + Info [UMFPACK_VARIABLE_PEAK_ESTIMATE]: the estimated peak size (in + Units) of the variable-sized part of the Numeric object. This is + usually an upper bound, but that is not guaranteed. + + Info [UMFPACK_VARIABLE_FINAL_ESTIMATE]: the estimated final size (in + Units) of the variable-sized part of the Numeric object. This is + usually an upper bound, but that is not guaranteed. It holds just + the sparse LU factors. + + Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]: an estimate of the final size (in + Units) of the entire Numeric object (both fixed-size and variable- + sized parts), which holds the LU factorization (including the L, U, + P and Q matrices). + + Info [UMFPACK_PEAK_MEMORY_ESTIMATE]: an estimate of the total amount of + memory (in Units) required by umfpack_*_symbolic and + umfpack_*_numeric to perform both the symbolic and numeric + factorization. This is the larger of the amount of memory needed + in umfpack_*_numeric itself, and the amount of memory needed in + umfpack_*_symbolic (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]). The + count includes the size of both the Symbolic and Numeric objects + themselves. It can be a very loose upper bound, particularly when + the symmetric or 2-by-2 strategies are used. + + Info [UMFPACK_FLOPS_ESTIMATE]: an estimate of the total floating-point + operations required to factorize the matrix. This is a "true" + theoretical estimate of the number of flops that would be performed + by a flop-parsimonious sparse LU algorithm. It assumes that no + extra flops are performed except for what is strictly required to + compute the LU factorization. It ignores, for example, the flops + performed by umfpack_di_numeric to add contribution blocks of + frontal matrices together. If L and U are the upper bound on the + pattern of the factors, then this flop count estimate can be + represented in MATLAB (for real matrices, not complex) as: + + Lnz = full (sum (spones (L))) - 1 ; % nz in each col of L + Unz = full (sum (spones (U')))' - 1 ; % nz in each row of U + flops = 2*Lnz*Unz + sum (Lnz) ; + + The actual "true flop" count found by umfpack_*_numeric will be + less than this estimate. + + For the real version, only (+ - * /) are counted. For the complex + version, the following counts are used: + + operation flops + c = 1/b 6 + c = a*b 6 + c -= a*b 8 + + Info [UMFPACK_LNZ_ESTIMATE]: an estimate of the number of nonzeros in + L, including the diagonal. Since L is unit-diagonal, the diagonal + of L is not stored. This estimate is a strict upper bound on the + actual nonzeros in L to be computed by umfpack_*_numeric. + + Info [UMFPACK_UNZ_ESTIMATE]: an estimate of the number of nonzeros in + U, including the diagonal. This estimate is a strict upper bound on + the actual nonzeros in U to be computed by umfpack_*_numeric. + + Info [UMFPACK_MAX_FRONT_SIZE_ESTIMATE]: estimate of the size of the + largest frontal matrix (# of entries), for arbitrary partial + pivoting during numerical factorization. + + Info [UMFPACK_SYMBOLIC_TIME]: The CPU time taken, in seconds. + + Info [UMFPACK_SYMBOLIC_WALLTIME]: The wallclock time taken, in seconds. + + Info [UMFPACK_STRATEGY_USED]: The ordering strategy used: + UMFPACK_STRATEGY_SYMMETRIC, UMFPACK_STRATEGY_UNSYMMETRIC, or + UMFPACK_STRATEGY_2BY2. + + Info [UMFPACK_ORDERING_USED]: The ordering method used: + UMFPACK_ORDERING_COLAMD or UMFPACK_ORDERING_AMD. It can be + UMFPACK_ORDERING_GIVEN for umfpack_*_qsymbolic. + + Info [UMFPACK_QFIXED]: 1 if the column pre-ordering will be refined + during numerical factorization, 0 if not. + + Info [UMFPACK_DIAG_PREFERED]: 1 if diagonal pivoting will be attempted, + 0 if not. + + Info [UMFPACK_COL_SINGLETONS]: the matrix A is analyzed by first + eliminating all pivots with zero Markowitz cost. This count is the + number of these pivots with exactly one nonzero in their pivot + column. + + Info [UMFPACK_ROW_SINGLETONS]: the number of zero-Markowitz-cost + pivots with exactly one nonzero in their pivot row. + + Info [UMFPACK_PATTERN_SYMMETRY]: the symmetry of the pattern of S. + + Info [UMFPACK_NZ_A_PLUS_AT]: the number of off-diagonal entries in S+S'. + + Info [UMFPACK_NZDIAG]: the number of entries on the diagonal of S. + + Info [UMFPACK_N2]: if S is square, and nempty_row = nempty_col, this + is equal to n_row - n1 - nempty_row. + + Info [UMFPACK_S_SYMMETRIC]: 1 if S is square and its diagonal has been + preserved, 0 otherwise. + + + Info [UMFPACK_MAX_FRONT_NROWS_ESTIMATE]: estimate of the max number of + rows in any frontal matrix, for arbitrary partial pivoting. + + Info [UMFPACK_MAX_FRONT_NCOLS_ESTIMATE]: estimate of the max number of + columns in any frontal matrix, for arbitrary partial pivoting. + + ------------------------------------------------------------------------ + The next four statistics are computed only if AMD is used: + ------------------------------------------------------------------------ + + Info [UMFPACK_SYMMETRIC_LUNZ]: The number of nonzeros in L and U, + assuming no pivoting during numerical factorization, and assuming a + zero-free diagonal of U. Excludes the entries on the diagonal of + L. If the matrix has a purely symmetric nonzero pattern, this is + often a lower bound on the nonzeros in the actual L and U computed + in the numerical factorization, for matrices that fit the criteria + for the "symmetric" strategy. + + Info [UMFPACK_SYMMETRIC_FLOPS]: The floating-point operation count in + the numerical factorization phase, assuming no pivoting. If the + pattern of the matrix is symmetric, this is normally a lower bound + on the floating-point operation count in the actual numerical + factorization, for matrices that fit the criteria for the symmetric + or 2-by-2 strategies + + Info [UMFPACK_SYMMETRIC_NDENSE]: The number of "dense" rows/columns of + S+S' that were ignored during the AMD ordering. These are placed + last in the output order. If > 0, then the + Info [UMFPACK_SYMMETRIC_*] statistics, above are rough upper bounds. + + Info [UMFPACK_SYMMETRIC_DMAX]: The maximum number of nonzeros in any + column of L, if no pivoting is performed during numerical + factorization. Excludes the part of the LU factorization for + pivots with zero Markowitz cost. + + ------------------------------------------------------------------------ + The following statistics are computed only if the 2-by-2 strategy is + used or attempted: + ------------------------------------------------------------------------ + + Info [UMFPACK_2BY2_NWEAK]: the number of small diagonal entries in S. + + Info [UMFPACK_2BY2_UNMATCHED]: the number of small diagonal entries + in P2*S. + + Info [UMFPACK_2BY2_PATTERN_SYMMETRY]: the symmetry of P2*S. + + Info [UMFPACK_2BY2_NZ_PA_PLUS_AT]: the number of off-diagonal entries + in (P2*S)+(P2*S)'. + + Info [UMFPACK_2BY2_NZDIAG]: the number of nonzero entries on the + diagonal of P2*S. + + + At the start of umfpack_*_symbolic, all of Info is set of -1, and then + after that only the above listed Info [...] entries are accessed. + Future versions might modify different parts of Info. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_tictoc.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_tictoc.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_tictoc.h @@ -0,0 +1,60 @@ +/* ========================================================================== */ +/* === umfpack_tictoc ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +void umfpack_tic (double stats [2]) ; + +void umfpack_toc (double stats [2]) ; + + +/* +Syntax (for all versions: di, dl, zi, and zl): + + #include "umfpack.h" + double stats [2] ; + umfpack_tic (stats) ; + ... + umfpack_toc (stats) ; + +Purpose: + + umfpack_tic returns the CPU time and wall clock time used by the process. + The CPU time includes both "user" and "system" time (the latter is time + spent by the system on behalf of the process, and is thus charged to the + process). umfpack_toc returns the CPU time and wall clock time since the + last call to umfpack_tic with the same stats array. + + Typical usage: + + umfpack_tic (stats) ; + ... do some work ... + umfpack_toc (stats) ; + + then stats [1] contains the time in seconds used by the code between + umfpack_tic and umfpack_toc, and stats [0] contains the wall clock time + elapsed between the umfpack_tic and umfpack_toc. These two routines act + just like tic and toc in MATLAB, except that the both process time and + wall clock time are returned. + + This routine normally uses the sysconf and times routines in the POSIX + standard. If -DNPOSIX is defined at compile time, then the ANSI C clock + routine is used instead, and only the CPU time is returned (stats [0] + is set to zero). + + umfpack_tic and umfpack_toc are the routines used internally in UMFPACK + to time the symbolic analysis, numerical factorization, and the forward/ + backward solve. + +Arguments: + + double stats [2]: + + stats [0]: wall clock time, in seconds + stats [1]: CPU time, in seconds +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_timer.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_timer.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_timer.h @@ -0,0 +1,39 @@ +/* ========================================================================== */ +/* === umfpack_timer ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +double umfpack_timer ( void ) ; + +/* +Syntax (for all versions: di, dl, zi, and zl): + + #include "umfpack.h" + double t ; + t = umfpack_timer ( ) ; + +Purpose: + + Returns the CPU time used by the process. Includes both "user" and "system" + time (the latter is time spent by the system on behalf of the process, and + is thus charged to the process). It does not return the wall clock time. + See umfpack_tic and umfpack_toc (the file umfpack_tictoc.h) for the timer + used internally by UMFPACK. + + This routine uses the Unix getrusage routine, if available. It is less + subject to overflow than the ANSI C clock routine. If getrusage is not + available, the portable ANSI C clock routine is used instead. + Unfortunately, clock ( ) overflows if the CPU time exceeds 2147 seconds + (about 36 minutes) when sizeof (clock_t) is 4 bytes. If you have getrusage, + be sure to compile UMFPACK with the -DGETRUSAGE flag set; see umf_config.h + and the User Guide for details. Even the getrusage routine can overlow. + +Arguments: + + None. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_transpose.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_transpose.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_transpose.h @@ -0,0 +1,216 @@ +/* ========================================================================== */ +/* === umfpack_transpose ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_transpose +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + const int P [ ], + const int Q [ ], + int Rp [ ], + int Ri [ ], + double Rx [ ] +) ; + +long umfpack_dl_transpose +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + const long P [ ], + const long Q [ ], + long Rp [ ], + long Ri [ ], + double Rx [ ] +) ; + +int umfpack_zi_transpose +( + int n_row, + int n_col, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + const int P [ ], + const int Q [ ], + int Rp [ ], + int Ri [ ], + double Rx [ ], double Rz [ ], + int do_conjugate +) ; + +long umfpack_zl_transpose +( + long n_row, + long n_col, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + const long P [ ], + const long Q [ ], + long Rp [ ], + long Ri [ ], + double Rx [ ], double Rz [ ], + long do_conjugate +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri ; + double *Ax, *Rx ; + status = umfpack_di_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, Rp, Ri, Rx) ; + +double long Syntax: + + #include "umfpack.h" + long n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri ; + double *Ax, *Rx ; + status = umfpack_dl_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, Rp, Ri, Rx) ; + +complex int Syntax: + + #include "umfpack.h" + int n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri, do_conjugate ; + double *Ax, *Az, *Rx, *Rz ; + status = umfpack_zi_transpose (n_row, n_col, Ap, Ai, Ax, Az, P, Q, + Rp, Ri, Rx, Rz, do_conjugate) ; + +complex long Syntax: + + #include "umfpack.h" + long n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri, do_conjugate ; + double *Ax, *Az, *Rx, *Rz ; + status = umfpack_zl_transpose (n_row, n_col, Ap, Ai, Ax, Az, P, Q, + Rp, Ri, Rx, Rz, do_conjugate) ; + +packed complex Syntax: + + Same as above, except Az are Rz are NULL. + +Purpose: + + Transposes and optionally permutes a sparse matrix in row or column-form, + R = (PAQ)'. In MATLAB notation, R = (A (P,Q))' or R = (A (P,Q)).' doing + either the linear algebraic transpose or the array transpose. Alternatively, + this routine can be viewed as converting A (P,Q) from column-form to + row-form, or visa versa (for the array transpose). Empty rows and columns + may exist. The matrix A may be singular and/or rectangular. + + umfpack_*_transpose is useful if you want to factorize A' or A.' instead of + A. Factorizing A' or A.' instead of A can be much better, particularly if + AA' is much sparser than A'A. You can still solve Ax=b if you factorize + A' or A.', by solving with the sys argument UMFPACK_At or UMFPACK_Aat, + respectively, in umfpack_*_*solve. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_out_of_memory if umfpack_*_transpose fails to allocate a + size-max (n_row,n_col) workspace. + UMFPACK_ERROR_argument_missing if Ai, Ap, Ri, and/or Rp are missing. + UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0 + UMFPACK_ERROR_invalid_permutation if P and/or Q are invalid. + UMFPACK_ERROR_invalid_matrix if Ap [n_col] < 0, if Ap [0] != 0, + if Ap [j] > Ap [j+1] for any j in the range 0 to n_col-1, + if any row index i is < 0 or >= n_row, or if the row indices + in any column are not in ascending order. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0. + + Int Ap [n_col+1] ; Input argument, not modified. + + The column pointers of the column-oriented form of the matrix A. See + umfpack_*_symbolic for a description. The number of entries in + the matrix is nz = Ap [n_col]. Ap [0] must be zero, Ap [n_col] must be + => 0, and Ap [j] <= Ap [j+1] and Ap [j] <= Ap [n_col] must be true for + all j in the range 0 to n_col-1. Empty columns are OK (that is, Ap [j] + may equal Ap [j+1] for any j in the range 0 to n_col-1). + + Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + + The nonzero pattern (row indices) for column j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j + must be in ascending order, and no duplicate row indices may be present. + Row indices must be in the range 0 to n_row-1 (the matrix is 0-based). + + double Ax [nz] ; Input argument, not modified, of size nz = Ap [n_col]. + Size 2*nz if Az or Rz are NULL. + double Az [nz] ; Input argument, not modified, for complex versions. + + If present, these are the numerical values of the sparse matrix A. + The nonzero pattern (row indices) for column j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)], and the corresponding real numerical + values are stored in Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary + values are stored in Az [(Ap [j]) ... (Ap [j+1]-1)]. The values are + transposed only if Ax and Rx are present. + This is not an error conditions; you are able to transpose + and permute just the pattern of a matrix. + + If Az or Rz are NULL, then both real + and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + Int P [n_row] ; Input argument, not modified. + + The permutation vector P is defined as P [k] = i, where the original + row i of A is the kth row of PAQ. If you want to use the identity + permutation for P, simply pass (Int *) NULL for P. This is not an error + condition. P is a complete permutation of all the rows of A; this + routine does not support the creation of a transposed submatrix of A + (R = A (1:3,:)' where A has more than 3 rows, for example, cannot be + done; a future version might support this operation). + + Int Q [n_col] ; Input argument, not modified. + + The permutation vector Q is defined as Q [k] = j, where the original + column j of A is the kth column of PAQ. If you want to use the identity + permutation for Q, simply pass (Int *) NULL for Q. This is not an error + condition. Q is a complete permutation of all the columns of A; this + routine does not support the creation of a transposed submatrix of A. + + Int Rp [n_row+1] ; Output argument. + + The column pointers of the matrix R = (A (P,Q))' or (A (P,Q)).', in the + same form as the column pointers Ap for the matrix A. + + Int Ri [nz] ; Output argument. + + The row indices of the matrix R = (A (P,Q))' or (A (P,Q)).' , in the + same form as the row indices Ai for the matrix A. + + double Rx [nz] ; Output argument. + Size 2*nz if Az or Rz are NULL. + double Rz [nz] ; Output argument, imaginary part for complex versions. + + If present, these are the numerical values of the sparse matrix R, + in the same form as the values Ax and Az of the matrix A. + + If Az or Rz are NULL, then both real + and imaginary parts are contained in Rx[0..2*nz-1], with Rx[2*k] + and Rx[2*k+1] being the real and imaginary part of the kth entry. + + Int do_conjugate ; Input argument for complex versions only. + + If true, and if Ax and Rx are present, then the linear + algebraic transpose is computed (complex conjugate). If false, the + array transpose is computed instead. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_triplet_to_col.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_triplet_to_col.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_triplet_to_col.h @@ -0,0 +1,263 @@ +/* ========================================================================== */ +/* === umfpack_triplet_to_col =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_triplet_to_col +( + int n_row, + int n_col, + int nz, + const int Ti [ ], + const int Tj [ ], + const double Tx [ ], + int Ap [ ], + int Ai [ ], + double Ax [ ], + int Map [ ] +) ; + +long umfpack_dl_triplet_to_col +( + long n_row, + long n_col, + long nz, + const long Ti [ ], + const long Tj [ ], + const double Tx [ ], + long Ap [ ], + long Ai [ ], + double Ax [ ], + long Map [ ] +) ; + +int umfpack_zi_triplet_to_col +( + int n_row, + int n_col, + int nz, + const int Ti [ ], + const int Tj [ ], + const double Tx [ ], const double Tz [ ], + int Ap [ ], + int Ai [ ], + double Ax [ ], double Az [ ], + int Map [ ] +) ; + +long umfpack_zl_triplet_to_col +( + long n_row, + long n_col, + long nz, + const long Ti [ ], + const long Tj [ ], + const double Tx [ ], const double Tz [ ], + long Ap [ ], + long Ai [ ], + double Ax [ ], double Az [ ], + long Map [ ] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + int n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ; + double *Tx, *Ax ; + status = umfpack_di_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, + Ap, Ai, Ax, Map) ; + +double long Syntax: + + #include "umfpack.h" + long n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ; + double *Tx, *Ax ; + status = umfpack_dl_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, + Ap, Ai, Ax, Map) ; + +complex int Syntax: + + #include "umfpack.h" + int n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ; + double *Tx, *Tz, *Ax, *Az ; + status = umfpack_zi_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, Tz, + Ap, Ai, Ax, Az, Map) ; + +long Syntax: + + #include "umfpack.h" + long n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ; + double *Tx, *Tz, *Ax, *Az ; + status = umfpack_zl_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, Tz, + Ap, Ai, Ax, Az, Map) ; + +packed complex Syntax: + + Same as above, except Tz and Az are NULL. + +Purpose: + + Converts a sparse matrix from "triplet" form to compressed-column form. + Analogous to A = spconvert (Ti, Tj, Tx + Tz*1i) in MATLAB, except that + zero entries present in the triplet form are present in A. + + The triplet form of a matrix is a very simple data structure for basic + sparse matrix operations. For example, suppose you wish to factorize a + matrix A coming from a finite element method, in which A is a sum of + dense submatrices, A = E1 + E2 + E3 + ... . The entries in each element + matrix Ei can be concatenated together in the three triplet arrays, and + any overlap between the elements will be correctly summed by + umfpack_*_triplet_to_col. + + Transposing a matrix in triplet form is simple; just interchange the + use of Ti and Tj. You can construct the complex conjugate transpose by + negating Tz, for the complex versions. + + Permuting a matrix in triplet form is also simple. If you want the matrix + PAQ, or A (P,Q) in MATLAB notation, where P [k] = i means that row i of + A is the kth row of PAQ and Q [k] = j means that column j of A is the kth + column of PAQ, then do the following. First, create inverse permutations + Pinv and Qinv such that Pinv [i] = k if P [k] = i and Qinv [j] = k if + Q [k] = j. Next, for the mth triplet (Ti [m], Tj [m], Tx [m], Tz [m]), + replace Ti [m] with Pinv [Ti [m]] and replace Tj [m] with Qinv [Tj [m]]. + + If you have a column-form matrix with duplicate entries or unsorted + columns, you can sort it and sum up the duplicates by first converting it + to triplet form with umfpack_*_col_to_triplet, and then converting it back + with umfpack_*_triplet_to_col. + + Constructing a submatrix is also easy. Just scan the triplets and remove + those entries outside the desired subset of 0...n_row-1 and 0...n_col-1, + and renumber the indices according to their position in the subset. + + You can do all these operations on a column-form matrix by first + converting it to triplet form with umfpack_*_col_to_triplet, doing the + operation on the triplet form, and then converting it back with + umfpack_*_triplet_to_col. + + The only operation not supported easily in the triplet form is the + multiplication of two sparse matrices (UMFPACK does not provide this + operation). + + You can print the input triplet form with umfpack_*_report_triplet, and + the output matrix with umfpack_*_report_matrix. + + The matrix may be singular (nz can be zero, and empty rows and/or columns + may exist). It may also be rectangular and/or complex. + +Returns: + + UMFPACK_OK if successful. + UMFPACK_ERROR_argument_missing if Ap, Ai, Ti, and/or Tj are missing. + UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0. + UMFPACK_ERROR_invalid_matrix if nz < 0, or if for any k, Ti [k] and/or + Tj [k] are not in the range 0 to n_row-1 or 0 to n_col-1, respectively. + UMFPACK_ERROR_out_of_memory if unable to allocate sufficient workspace. + +Arguments: + + Int n_row ; Input argument, not modified. + Int n_col ; Input argument, not modified. + + A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0. + All row and column indices in the triplet form must be in the range + 0 to n_row-1 and 0 to n_col-1, respectively. + + Int nz ; Input argument, not modified. + + The number of entries in the triplet form of the matrix. Restriction: + nz >= 0. + + Int Ti [nz] ; Input argument, not modified. + Int Tj [nz] ; Input argument, not modified. + double Tx [nz] ; Input argument, not modified. + Size 2*nz if Tz or Az are NULL. + double Tz [nz] ; Input argument, not modified, for complex versions. + + Ti, Tj, Tx, and Tz hold the "triplet" form of a sparse matrix. The kth + nonzero entry is in row i = Ti [k], column j = Tj [k], and the real part + of a_ij is Tx [k]. The imaginary part of a_ij is Tz [k], for complex + versions. The row and column indices i and j must be in the range 0 to + n_row-1 and 0 to n_col-1, respectively. Duplicate entries may be + present; they are summed in the output matrix. This is not an error + condition. The "triplets" may be in any order. Tx, Tz, Ax, and Az + are optional. Ax is computed only if both Ax and Tx are present + (not (double *) NULL). This is not error condition; the routine can + create just the pattern of the output matrix from the pattern of the + triplets. + + If Az or Tz are NULL, then both real + and imaginary parts are contained in Tx[0..2*nz-1], with Tx[2*k] + and Tx[2*k+1] being the real and imaginary part of the kth entry. + + Int Ap [n_col+1] ; Output argument. + + Ap is an integer array of size n_col+1 on input. On output, Ap holds + the "pointers" for the column form of the sparse matrix A. Column j of + the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)]. The first + entry, Ap [0], is zero, and Ap [j] <= Ap [j+1] holds for all j in the + range 0 to n_col-1. The value nz2 = Ap [n_col] is thus the total + number of entries in the pattern of the matrix A. Equivalently, the + number of duplicate triplets is nz - Ap [n_col]. + + Int Ai [nz] ; Output argument. + + Ai is an integer array of size nz on input. Note that only the first + Ap [n_col] entries are used. + + The nonzero pattern (row indices) for column j is stored in + Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j + are in ascending order, and no duplicate row indices are present. + Row indices are in the range 0 to n_col-1 (the matrix is 0-based). + + double Ax [nz] ; Output argument. Size 2*nz if Tz or Az are NULL. + double Az [nz] ; Output argument for complex versions. + + Ax and Az (for the complex versions) are double arrays of size nz on + input. Note that only the first Ap [n_col] entries are used + in both arrays. + + Ax is optional; if Tx and/or Ax are not present (a (double *) NULL + pointer), then Ax is not computed. If present, Ax holds the + numerical values of the the real part of the sparse matrix A and Az + holds the imaginary parts. The nonzero pattern (row indices) for + column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the + corresponding numerical values are stored in + Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary parts are stored in + Az [(Ap [j]) ... (Ap [j+1]-1)], for the complex versions. + + If Az or Tz are NULL, then both real + and imaginary parts are returned in Ax[0..2*nz2-1], with Ax[2*k] + and Ax[2*k+1] being the real and imaginary part of the kth entry. + + int Map [nz] ; Optional output argument. + + If Map is present (a non-NULL pointer to an Int array of size nz), then + on output it holds the position of the triplets in the column-form + matrix. That is, suppose p = Map [k], and the k-th triplet is i=Ti[k], + j=Tj[k], and aij=Tx[k]. Then i=Ai[p], and aij will have been summed + into Ax[p] (or simply aij=Ax[p] if there were no duplicate entries also + in row i and column j). Also, Ap[j] <= p < Ap[j+1]. The Map array is + not computed if it is (Int *) NULL. The Map array is useful for + converting a subsequent triplet form matrix with the same pattern as the + first one, without calling this routine. If Ti and Tj do not change, + then Ap, and Ai can be reused from the prior call to + umfpack_*_triplet_to_col. You only need to recompute Ax (and Az for the + split complex version). This code excerpt properly sums up all + duplicate values (for the real version): + + for (p = 0 ; p < Ap [n_col] ; p++) Ax [p] = 0 ; + for (k = 0 ; k < nz ; k++) Ax [Map [k]] += Tx [k] ; + + This feature is useful (along with the reuse of the Symbolic object) if + you need to factorize a sequence of triplet matrices with identical + nonzero pattern (the order of the triplets in the Ti,Tj,Tx arrays must + also remain unchanged). It is faster than calling this routine for + each matrix, and requires no workspace. +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Include/umfpack_wsolve.h b/liboctave/UMFPACK/UMFPACK/Include/umfpack_wsolve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Include/umfpack_wsolve.h @@ -0,0 +1,172 @@ +/* ========================================================================== */ +/* === umfpack_wsolve ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +int umfpack_di_wsolve +( + int sys, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], + double X [ ], + const double B [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO], + int Wi [ ], + double W [ ] +) ; + +long umfpack_dl_wsolve +( + long sys, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], + double X [ ], + const double B [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO], + long Wi [ ], + double W [ ] +) ; + +int umfpack_zi_wsolve +( + int sys, + const int Ap [ ], + const int Ai [ ], + const double Ax [ ], const double Az [ ], + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO], + int Wi [ ], + double W [ ] +) ; + +long umfpack_zl_wsolve +( + long sys, + const long Ap [ ], + const long Ai [ ], + const double Ax [ ], const double Az [ ], + double Xx [ ], double Xz [ ], + const double Bx [ ], const double Bz [ ], + void *Numeric, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO], + long Wi [ ], + double W [ ] +) ; + +/* +double int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, *Ap, *Ai, *Wi, sys ; + double *B, *X, *Ax, *W, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_di_wsolve (sys, Ap, Ai, Ax, X, B, Numeric, + Control, Info, Wi, W) ; + +double long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, *Ap, *Ai, *Wi, sys ; + double *B, *X, *Ax, *W, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_dl_wsolve (sys, Ap, Ai, Ax, X, B, Numeric, + Control, Info, Wi, W) ; + +complex int Syntax: + + #include "umfpack.h" + void *Numeric ; + int status, *Ap, *Ai, *Wi, sys ; + double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, *W, + Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_zi_wsolve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, + Control, Info, Wi, W) ; + +complex long Syntax: + + #include "umfpack.h" + void *Numeric ; + long status, *Ap, *Ai, *Wi, sys ; + double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, *W, + Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ; + status = umfpack_zl_wsolve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric, + Control, Info, Wi, W) ; + +packed complex Syntax: + + Same as above, except Az, Xz, and Bz are NULL. + +Purpose: + + Given LU factors computed by umfpack_*_numeric (PAQ=LU) and the + right-hand-side, B, solve a linear system for the solution X. Iterative + refinement is optionally performed. This routine is identical to + umfpack_*_solve, except that it does not dynamically allocate any workspace. + When you have many linear systems to solve, this routine is faster than + umfpack_*_solve, since the workspace (Wi, W) needs to be allocated only + once, prior to calling umfpack_*_wsolve. + +Returns: + + The status code is returned. See Info [UMFPACK_STATUS], below. + +Arguments: + + Int sys ; Input argument, not modified. + Int Ap [n+1] ; Input argument, not modified. + Int Ai [nz] ; Input argument, not modified. + double Ax [nz] ; Input argument, not modified. + Size 2*nz in packed complex case. + double X [n] ; Output argument. + double B [n] ; Input argument, not modified. + void *Numeric ; Input argument, not modified. + double Control [UMFPACK_CONTROL] ; Input argument, not modified. + double Info [UMFPACK_INFO] ; Output argument. + + for complex versions: + double Az [nz] ; Input argument, not modified, imaginary part + double Xx [n] ; Output argument, real part. + Size 2*n in packed complex case. + double Xz [n] ; Output argument, imaginary part + double Bx [n] ; Input argument, not modified, real part. + Size 2*n in packed complex case. + double Bz [n] ; Input argument, not modified, imaginary part + + The above arguments are identical to umfpack_*_solve, except that the + error code UMFPACK_ERROR_out_of_memory will not be returned in + Info [UMFPACK_STATUS], since umfpack_*_wsolve does not allocate any + memory. + + Int Wi [n] ; Workspace. + double W [c*n] ; Workspace, where c is defined below. + + The Wi and W arguments are workspace used by umfpack_*_wsolve. They + need not be initialized on input, and their contents are undefined on + output. The size of W depends on whether or not iterative refinement is + used, and which version (real or complex) is called. Iterative + refinement is performed if Ax=b, A'x=b, or A.'x=b is being solved, + Control [UMFPACK_IRSTEP] > 0, and A is nonsingular. The size of W is + given below: + + no iter. with iter. + refinement refinement + umfpack_di_wsolve n 5*n + umfpack_dl_wsolve n 5*n + umfpack_zi_wsolve 4*n 10*n + umfpack_zl_wsolve 4*n 10*n +*/ diff --git a/liboctave/UMFPACK/UMFPACK/Lib/libumfpack.def b/liboctave/UMFPACK/UMFPACK/Lib/libumfpack.def new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Lib/libumfpack.def @@ -0,0 +1,105 @@ +LIBRARY libumfpack.dll +EXPORTS +umfpack_di_col_to_triplet +umfpack_di_defaults +umfpack_di_free_numeric +umfpack_di_free_symbolic +umfpack_di_get_numeric +umfpack_di_get_lunz +umfpack_di_get_symbolic +umfpack_di_get_determinant +umfpack_di_numeric +umfpack_di_qsymbolic +umfpack_di_report_control +umfpack_di_report_info +umfpack_di_report_matrix +umfpack_di_report_numeric +umfpack_di_report_perm +umfpack_di_report_status +umfpack_di_report_symbolic +umfpack_di_report_triplet +umfpack_di_report_vector +umfpack_di_solve +umfpack_di_wsolve +umfpack_di_symbolic +umfpack_di_transpose +umfpack_di_triplet_to_col +umfpack_di_scale +umfpack_dl_col_to_triplet +umfpack_dl_defaults +umfpack_dl_free_numeric +umfpack_dl_free_symbolic +umfpack_dl_get_numeric +umfpack_dl_get_lunz +umfpack_dl_get_symbolic +umfpack_dl_get_determinant +umfpack_dl_numeric +umfpack_dl_qsymbolic +umfpack_dl_report_control +umfpack_dl_report_info +umfpack_dl_report_matrix +umfpack_dl_report_numeric +umfpack_dl_report_perm +umfpack_dl_report_status +umfpack_dl_report_symbolic +umfpack_dl_report_triplet +umfpack_dl_report_vector +umfpack_dl_solve +umfpack_dl_wsolve +umfpack_dl_symbolic +umfpack_dl_transpose +umfpack_dl_triplet_to_col +umfpack_dl_scale +umfpack_zi_col_to_triplet +umfpack_zi_defaults +umfpack_zi_free_numeric +umfpack_zi_free_symbolic +umfpack_zi_get_numeric +umfpack_zi_get_lunz +umfpack_zi_get_symbolic +umfpack_zi_get_determinant +umfpack_zi_numeric +umfpack_zi_qsymbolic +umfpack_zi_report_control +umfpack_zi_report_info +umfpack_zi_report_matrix +umfpack_zi_report_numeric +umfpack_zi_report_perm +umfpack_zi_report_status +umfpack_zi_report_symbolic +umfpack_zi_report_triplet +umfpack_zi_report_vector +umfpack_zi_solve +umfpack_zi_wsolve +umfpack_zi_symbolic +umfpack_zi_transpose +umfpack_zi_triplet_to_col +umfpack_zi_scale +umfpack_zl_col_to_triplet +umfpack_zl_defaults +umfpack_zl_free_numeric +umfpack_zl_free_symbolic +umfpack_zl_get_numeric +umfpack_zl_get_lunz +umfpack_zl_get_symbolic +umfpack_zl_get_determinant +umfpack_zl_numeric +umfpack_zl_qsymbolic +umfpack_zl_report_control +umfpack_zl_report_info +umfpack_zl_report_matrix +umfpack_zl_report_numeric +umfpack_zl_report_perm +umfpack_zl_report_status +umfpack_zl_report_symbolic +umfpack_zl_report_triplet +umfpack_zl_report_vector +umfpack_zl_solve +umfpack_zl_wsolve +umfpack_zl_symbolic +umfpack_zl_transpose +umfpack_zl_triplet_to_col +umfpack_zl_scale +umfpack_timer +umfpack_tic +umfpack_toc diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/Contents.m b/liboctave/UMFPACK/UMFPACK/MATLAB/Contents.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/Contents.m @@ -0,0 +1,24 @@ +%Contents of the UMFPACK sparse matrix toolbox: +% +% umfpack computes x=A\b, x=A/b, or lu (A) for a sparse matrix A +% umfpack_make to compile umfpack for use in MATLAB +% umfpack_details details on all the options for using umfpack in MATLAB +% umfpack_report prints optional control settings and statistics +% umfpack_demo a long demo +% umfpack_simple a simple demo +% umfpack_btf factorize A using a block triangular form +% umfpack_solve x = A\b or x = b/A +% lu_normest estimates norm (L*U-A, 1) without forming L*U-A +% luflop given L and U, computes # of flops required to compute them +% umfpack_test for testing umfpack (requires UFget interface to UF sparse +% matrix collection) +% +% See also: +% amd symmetric minimum degree ordering +% colamd unsymmetric column approx minimum degree ordering +% symamd symmetric approx minimum degree ordering, based on colamd +% +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +help Contents diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/GNUmakefile b/liboctave/UMFPACK/UMFPACK/MATLAB/GNUmakefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/GNUmakefile @@ -0,0 +1,229 @@ +#------------------------------------------------------------------------------- +# UMFPACK GNUmakefile for the UMFPACK MATLAB mexFunction (GNU "make" only) +#------------------------------------------------------------------------------- + +all: umfpack luflop + +include ../Make/Make.include + +MX = $(MEX) -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- + +# non-user-callable umf_*.[ch] files: +UMFCH = umf_assemble umf_blas3_update \ + umf_build_tuples umf_create_element \ + umf_dump umf_extend_front umf_garbage_collection \ + umf_get_memory umf_init_front umf_kernel \ + umf_kernel_init umf_kernel_wrapup \ + umf_local_search umf_lsolve umf_ltsolve \ + umf_mem_alloc_element umf_mem_alloc_head_block \ + umf_mem_alloc_tail_block umf_mem_free_tail_block \ + umf_mem_init_memoryspace \ + umf_report_vector umf_row_search umf_scale_column \ + umf_set_stats umf_solve umf_symbolic_usage umf_transpose \ + umf_tuple_lengths umf_usolve umf_utsolve umf_valid_numeric \ + umf_valid_symbolic umf_grow_front umf_start_front umf_2by2 \ + umf_store_lu umf_scale + +# non-user-callable umf_*.[ch] files, int/long versions only (no real/complex): +UMFINT = umf_analyze umf_apply_order umf_colamd umf_free umf_fsize \ + umf_is_permutation umf_malloc umf_realloc umf_report_perm \ + umf_singletons + +# non-user-callable and user-callable amd_*.[ch] files (int/long versions only): +AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ + amd_order amd_control amd_info amd_valid amd_preprocess + +# non-user-callable, created from umf_ltsolve.c, umf_utsolve.c, +# umf_triplet.c, and umf_assemble.c , with int/long and real/complex versions: +UMF_CREATED = umf_lhsolve umf_uhsolve umf_triplet_map_nox \ + umf_triplet_nomap_x umf_triplet_nomap_nox umf_triplet_map_x \ + umf_assemble_fixq umf_store_lu_drop + +# non-user-callable, int/long and real/complex versions: +UMF = $(UMF_CREATED) $(UMFCH) + +# user-callable umfpack_*.[ch] files (int/long and real/complex): +UMFPACK = umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ + umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ + umfpack_get_symbolic umfpack_get_determinant umfpack_numeric \ + umfpack_qsymbolic umfpack_report_control umfpack_report_info \ + umfpack_report_matrix umfpack_report_numeric umfpack_report_perm \ + umfpack_report_status umfpack_report_symbolic umfpack_report_triplet \ + umfpack_report_vector umfpack_solve umfpack_symbolic \ + umfpack_transpose umfpack_triplet_to_col umfpack_scale \ + umfpack_load_numeric umfpack_save_numeric \ + umfpack_load_symbolic umfpack_save_symbolic + +# user-callable, created from umfpack_solve.c (umfpack_wsolve.h exists, though): +# with int/long and real/complex versions: +UMFPACKW = umfpack_wsolve + +USER = $(UMFPACKW) $(UMFPACK) + +# user-callable, only one version for int/long, real/complex, *.[ch] files: +GENERIC = umfpack_timer umfpack_tictoc + +#------------------------------------------------------------------------------- +# include files: +#------------------------------------------------------------------------------- + +AMDH = ../../AMD/Source/amd_internal.h ../../AMD/Include/amd.h + +INC1 = umf_config.h umf_version.h umf_internal.h umf_triplet.h + +INC = ../Include/umfpack.h \ + $(addprefix ../Source/, $(INC1)) \ + $(addprefix ../Source/, $(addsuffix .h,$(UMFCH))) \ + $(addprefix ../Source/, $(addsuffix .h,$(UMFINT))) \ + $(addprefix ../Include/, $(addsuffix .h,$(USER))) \ + $(addprefix ../Include/, $(addsuffix .h,$(GENERIC))) \ + $(AMDH) + +#------------------------------------------------------------------------------- +# Create the umfpack and amd mexFunctions for MATLAB (int versions only) +#------------------------------------------------------------------------------- + +MEXI = $(addsuffix .o, $(subst umf_,umf_m_,$(UMFINT))) +MEXDI = $(addsuffix .o, $(subst umf_,umf_md_,$(UMF)) $(subst umfpack_,umfpack_md_,$(USER))) +MEXZI = $(addsuffix .o, $(subst umf_,umf_mz_,$(UMF)) $(subst umfpack_,umfpack_mz_,$(USER)) ) +MEXAMD = $(addsuffix .o, $(subst amd_,amd_m_,$(AMD))) +MEXGN = $(addsuffix .o, $(subst umfpack_,umfpack_m_,$(GENERIC))) + +MEXUMFPACK = $(MEXI) $(MEXDI) $(MEXZI) $(MEXGN) + +# Note that mex has no "-o" option, thus the need for $(MV) commands. +# If it did, then the rules would be much simpler: +# $(MX) -DDINT -c $< -o $@ + +#---------------------------------------- +# integer-only routines (no real/complex): +#---------------------------------------- + +amd_m_%.o: ../../AMD/Source/amd_%.c $(AMDH) + $(MX) -DDINT -c $< + - $(MV) amd_$*.o $@ + +umf_m_%.o: ../Source/umf_%.c $(INC) + $(MX) -DDINT -c $< + - $(MV) umf_$*.o $@ + +#---------------------------------------- +# Double precision, int version, for MATLAB +#---------------------------------------- + +umf_md_%.o: ../Source/umf_%.c $(INC) + $(MX) -DDINT -c $< + - $(MV) umf_$*.o $@ + +umf_md_%hsolve.o: ../Source/umf_%tsolve.c $(INC) + $(MX) -DDINT -DCONJUGATE_SOLVE -c $< + - $(MV) umf_$*tsolve.o $@ + +umf_md_triplet_map_x.o: ../Source/umf_triplet.c $(INC) + $(MX) -DDINT -DDO_MAP -DDO_VALUES -c $< + - $(MV) umf_triplet.o $@ + +umf_md_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) + $(MX) -DDINT -DDO_MAP -c $< + - $(MV) umf_triplet.o $@ + +umf_md_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) + $(MX) -DDINT -DDO_VALUES -c $< + - $(MV) umf_triplet.o $@ + +umf_md_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) + $(MX) -DDINT -c $< + - $(MV) umf_triplet.o $@ + +umf_md_assemble_fixq.o: ../Source/umf_assemble.c $(INC) + $(MX) -DDINT -DFIXQ -c $< + - $(MV) umf_assemble.o $@ + +umf_md_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) + $(MX) -DDINT -DDROP -c $< + - $(MV) umf_store_lu.o $@ + +umfpack_md_wsolve.o: ../Source/umfpack_solve.c $(INC) + $(MX) -DDINT -DWSOLVE -c $< + - $(MV) umfpack_solve.o $@ + +umfpack_md_%.o: ../Source/umfpack_%.c $(INC) + $(MX) -DDINT -c $< + - $(MV) umfpack_$*.o $@ + +#---------------------------------------- +# Complex double precision, int version, for MATLAB +#---------------------------------------- + +umf_mz_%.o: ../Source/umf_%.c $(INC) + $(MX) -DZINT -c $< + - $(MV) umf_$*.o $@ + +umf_mz_%hsolve.o: ../Source/umf_%tsolve.c $(INC) + $(MX) -DZINT -DCONJUGATE_SOLVE -c $< + - $(MV) umf_$*tsolve.o $@ + +umf_mz_triplet_map_x.o: ../Source/umf_triplet.c $(INC) + $(MX) -DZINT -DDO_MAP -DDO_VALUES -c $< + - $(MV) umf_triplet.o $@ + +umf_mz_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) + $(MX) -DZINT -DDO_MAP -c $< + - $(MV) umf_triplet.o $@ + +umf_mz_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) + $(MX) -DZINT -DDO_VALUES -c $< + - $(MV) umf_triplet.o $@ + +umf_mz_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) + $(MX) -DZINT -c $< + - $(MV) umf_triplet.o $@ + +umf_mz_assemble_fixq.o: ../Source/umf_assemble.c $(INC) + $(MX) -DZINT -DFIXQ -c $< + - $(MV) umf_assemble.o $@ + +umf_mz_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) + $(MX) -DZINT -DDROP -c $< + - $(MV) umf_store_lu.o $@ + +umfpack_mz_wsolve.o: ../Source/umfpack_solve.c $(INC) + $(MX) -DZINT -DWSOLVE -c $< + - $(MV) umfpack_solve.o $@ + +umfpack_mz_%.o: ../Source/umfpack_%.c $(INC) + $(MX) -DZINT -c $< + - $(MV) umfpack_$*.o $@ + +#---------------------------------------- +# Generic routines for MATLAB +#---------------------------------------- + +umfpack_m_timer.o: ../Source/umfpack_timer.c $(INC) + $(MX) -c $< + - $(MV) umfpack_timer.o $@ + +umfpack_m_tictoc.o: ../Source/umfpack_tictoc.c $(INC) + $(MX) -c $< + - $(MV) umfpack_tictoc.o $@ + +#---------------------------------------- +# umfpack mexFunction +#---------------------------------------- + +umfpack: umfpackmex.c $(MEXUMFPACK) $(MEXAMD) + $(MX) -output umfpack umfpackmex.c $(MEXUMFPACK) $(MEXAMD) + +luflop: luflopmex.c + $(MX) -output luflop luflopmex.c + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) *.mex* *.dll diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/Makefile b/liboctave/UMFPACK/UMFPACK/MATLAB/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/Makefile @@ -0,0 +1,439 @@ +#------------------------------------------------------------------------------- +# UMFPACK Makefile for the UMFPACK MATLAB mexFunction (old "make" only) +#------------------------------------------------------------------------------- + +# This is a very ugly Makefile, and is only provided for those who do not +# have GNU make. Note that it is not used if you have GNU make. It ignores +# dependency checking and just compiles everything. It was created +# automatically, via make -n using the GNUmakefile. That way, I don't have +# maintain two Makefiles. + +all: umfpack luflop + +include ../Make/Make.include + +MX = $(MEX) -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source + +umfpack: + $(MX) -DDINT -c ../Source/umf_analyze.c + $(MV) -f umf_analyze.o umf_m_analyze.o + $(MX) -DDINT -c ../Source/umf_apply_order.c + $(MV) -f umf_apply_order.o umf_m_apply_order.o + $(MX) -DDINT -c ../Source/umf_colamd.c + $(MV) -f umf_colamd.o umf_m_colamd.o + $(MX) -DDINT -c ../Source/umf_free.c + $(MV) -f umf_free.o umf_m_free.o + $(MX) -DDINT -c ../Source/umf_fsize.c + $(MV) -f umf_fsize.o umf_m_fsize.o + $(MX) -DDINT -c ../Source/umf_is_permutation.c + $(MV) -f umf_is_permutation.o umf_m_is_permutation.o + $(MX) -DDINT -c ../Source/umf_malloc.c + $(MV) -f umf_malloc.o umf_m_malloc.o + $(MX) -DDINT -c ../Source/umf_realloc.c + $(MV) -f umf_realloc.o umf_m_realloc.o + $(MX) -DDINT -c ../Source/umf_report_perm.c + $(MV) -f umf_report_perm.o umf_m_report_perm.o + $(MX) -DDINT -c ../Source/umf_singletons.c + $(MV) -f umf_singletons.o umf_m_singletons.o + $(MX) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c + $(MV) -f umf_ltsolve.o umf_md_lhsolve.o + $(MX) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c + $(MV) -f umf_utsolve.o umf_md_uhsolve.o + $(MX) -DDINT -DDO_MAP -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_md_triplet_map_nox.o + $(MX) -DDINT -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_md_triplet_nomap_x.o + $(MX) -DDINT -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_md_triplet_nomap_nox.o + $(MX) -DDINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_md_triplet_map_x.o + $(MX) -DDINT -DFIXQ -c ../Source/umf_assemble.c + $(MV) -f umf_assemble.o umf_md_assemble_fixq.o + $(MX) -DDINT -DDROP -c ../Source/umf_store_lu.c + $(MV) -f umf_store_lu.o umf_md_store_lu_drop.o + $(MX) -DDINT -c ../Source/umf_assemble.c + $(MV) -f umf_assemble.o umf_md_assemble.o + $(MX) -DDINT -c ../Source/umf_blas3_update.c + $(MV) -f umf_blas3_update.o umf_md_blas3_update.o + $(MX) -DDINT -c ../Source/umf_build_tuples.c + $(MV) -f umf_build_tuples.o umf_md_build_tuples.o + $(MX) -DDINT -c ../Source/umf_create_element.c + $(MV) -f umf_create_element.o umf_md_create_element.o + $(MX) -DDINT -c ../Source/umf_dump.c + $(MV) -f umf_dump.o umf_md_dump.o + $(MX) -DDINT -c ../Source/umf_extend_front.c + $(MV) -f umf_extend_front.o umf_md_extend_front.o + $(MX) -DDINT -c ../Source/umf_garbage_collection.c + $(MV) -f umf_garbage_collection.o umf_md_garbage_collection.o + $(MX) -DDINT -c ../Source/umf_get_memory.c + $(MV) -f umf_get_memory.o umf_md_get_memory.o + $(MX) -DDINT -c ../Source/umf_init_front.c + $(MV) -f umf_init_front.o umf_md_init_front.o + $(MX) -DDINT -c ../Source/umf_kernel.c + $(MV) -f umf_kernel.o umf_md_kernel.o + $(MX) -DDINT -c ../Source/umf_kernel_init.c + $(MV) -f umf_kernel_init.o umf_md_kernel_init.o + $(MX) -DDINT -c ../Source/umf_kernel_wrapup.c + $(MV) -f umf_kernel_wrapup.o umf_md_kernel_wrapup.o + $(MX) -DDINT -c ../Source/umf_local_search.c + $(MV) -f umf_local_search.o umf_md_local_search.o + $(MX) -DDINT -c ../Source/umf_lsolve.c + $(MV) -f umf_lsolve.o umf_md_lsolve.o + $(MX) -DDINT -c ../Source/umf_ltsolve.c + $(MV) -f umf_ltsolve.o umf_md_ltsolve.o + $(MX) -DDINT -c ../Source/umf_mem_alloc_element.c + $(MV) -f umf_mem_alloc_element.o umf_md_mem_alloc_element.o + $(MX) -DDINT -c ../Source/umf_mem_alloc_head_block.c + $(MV) -f umf_mem_alloc_head_block.o umf_md_mem_alloc_head_block.o + $(MX) -DDINT -c ../Source/umf_mem_alloc_tail_block.c + $(MV) -f umf_mem_alloc_tail_block.o umf_md_mem_alloc_tail_block.o + $(MX) -DDINT -c ../Source/umf_mem_free_tail_block.c + $(MV) -f umf_mem_free_tail_block.o umf_md_mem_free_tail_block.o + $(MX) -DDINT -c ../Source/umf_mem_init_memoryspace.c + $(MV) -f umf_mem_init_memoryspace.o umf_md_mem_init_memoryspace.o + $(MX) -DDINT -c ../Source/umf_report_vector.c + $(MV) -f umf_report_vector.o umf_md_report_vector.o + $(MX) -DDINT -c ../Source/umf_row_search.c + $(MV) -f umf_row_search.o umf_md_row_search.o + $(MX) -DDINT -c ../Source/umf_scale_column.c + $(MV) -f umf_scale_column.o umf_md_scale_column.o + $(MX) -DDINT -c ../Source/umf_set_stats.c + $(MV) -f umf_set_stats.o umf_md_set_stats.o + $(MX) -DDINT -c ../Source/umf_solve.c + $(MV) -f umf_solve.o umf_md_solve.o + $(MX) -DDINT -c ../Source/umf_symbolic_usage.c + $(MV) -f umf_symbolic_usage.o umf_md_symbolic_usage.o + $(MX) -DDINT -c ../Source/umf_transpose.c + $(MV) -f umf_transpose.o umf_md_transpose.o + $(MX) -DDINT -c ../Source/umf_tuple_lengths.c + $(MV) -f umf_tuple_lengths.o umf_md_tuple_lengths.o + $(MX) -DDINT -c ../Source/umf_usolve.c + $(MV) -f umf_usolve.o umf_md_usolve.o + $(MX) -DDINT -c ../Source/umf_utsolve.c + $(MV) -f umf_utsolve.o umf_md_utsolve.o + $(MX) -DDINT -c ../Source/umf_valid_numeric.c + $(MV) -f umf_valid_numeric.o umf_md_valid_numeric.o + $(MX) -DDINT -c ../Source/umf_valid_symbolic.c + $(MV) -f umf_valid_symbolic.o umf_md_valid_symbolic.o + $(MX) -DDINT -c ../Source/umf_grow_front.c + $(MV) -f umf_grow_front.o umf_md_grow_front.o + $(MX) -DDINT -c ../Source/umf_start_front.c + $(MV) -f umf_start_front.o umf_md_start_front.o + $(MX) -DDINT -c ../Source/umf_2by2.c + $(MV) -f umf_2by2.o umf_md_2by2.o + $(MX) -DDINT -c ../Source/umf_store_lu.c + $(MV) -f umf_store_lu.o umf_md_store_lu.o + $(MX) -DDINT -c ../Source/umf_scale.c + $(MV) -f umf_scale.o umf_md_scale.o + $(MX) -DDINT -DWSOLVE -c ../Source/umfpack_solve.c + $(MV) -f umfpack_solve.o umfpack_md_wsolve.o + $(MX) -DDINT -c ../Source/umfpack_col_to_triplet.c + $(MV) -f umfpack_col_to_triplet.o umfpack_md_col_to_triplet.o + $(MX) -DDINT -c ../Source/umfpack_defaults.c + $(MV) -f umfpack_defaults.o umfpack_md_defaults.o + $(MX) -DDINT -c ../Source/umfpack_free_numeric.c + $(MV) -f umfpack_free_numeric.o umfpack_md_free_numeric.o + $(MX) -DDINT -c ../Source/umfpack_free_symbolic.c + $(MV) -f umfpack_free_symbolic.o umfpack_md_free_symbolic.o + $(MX) -DDINT -c ../Source/umfpack_get_numeric.c + $(MV) -f umfpack_get_numeric.o umfpack_md_get_numeric.o + $(MX) -DDINT -c ../Source/umfpack_get_lunz.c + $(MV) -f umfpack_get_lunz.o umfpack_md_get_lunz.o + $(MX) -DDINT -c ../Source/umfpack_get_symbolic.c + $(MV) -f umfpack_get_symbolic.o umfpack_md_get_symbolic.o + $(MX) -DDINT -c ../Source/umfpack_get_determinant.c + $(MV) -f umfpack_get_determinant.o umfpack_md_get_determinant.o + $(MX) -DDINT -c ../Source/umfpack_numeric.c + $(MV) -f umfpack_numeric.o umfpack_md_numeric.o + $(MX) -DDINT -c ../Source/umfpack_qsymbolic.c + $(MV) -f umfpack_qsymbolic.o umfpack_md_qsymbolic.o + $(MX) -DDINT -c ../Source/umfpack_report_control.c + $(MV) -f umfpack_report_control.o umfpack_md_report_control.o + $(MX) -DDINT -c ../Source/umfpack_report_info.c + $(MV) -f umfpack_report_info.o umfpack_md_report_info.o + $(MX) -DDINT -c ../Source/umfpack_report_matrix.c + $(MV) -f umfpack_report_matrix.o umfpack_md_report_matrix.o + $(MX) -DDINT -c ../Source/umfpack_report_numeric.c + $(MV) -f umfpack_report_numeric.o umfpack_md_report_numeric.o + $(MX) -DDINT -c ../Source/umfpack_report_perm.c + $(MV) -f umfpack_report_perm.o umfpack_md_report_perm.o + $(MX) -DDINT -c ../Source/umfpack_report_status.c + $(MV) -f umfpack_report_status.o umfpack_md_report_status.o + $(MX) -DDINT -c ../Source/umfpack_report_symbolic.c + $(MV) -f umfpack_report_symbolic.o umfpack_md_report_symbolic.o + $(MX) -DDINT -c ../Source/umfpack_report_triplet.c + $(MV) -f umfpack_report_triplet.o umfpack_md_report_triplet.o + $(MX) -DDINT -c ../Source/umfpack_report_vector.c + $(MV) -f umfpack_report_vector.o umfpack_md_report_vector.o + $(MX) -DDINT -c ../Source/umfpack_solve.c + $(MV) -f umfpack_solve.o umfpack_md_solve.o + $(MX) -DDINT -c ../Source/umfpack_symbolic.c + $(MV) -f umfpack_symbolic.o umfpack_md_symbolic.o + $(MX) -DDINT -c ../Source/umfpack_transpose.c + $(MV) -f umfpack_transpose.o umfpack_md_transpose.o + $(MX) -DDINT -c ../Source/umfpack_triplet_to_col.c + $(MV) -f umfpack_triplet_to_col.o umfpack_md_triplet_to_col.o + $(MX) -DDINT -c ../Source/umfpack_scale.c + $(MV) -f umfpack_scale.o umfpack_md_scale.o + $(MX) -DDINT -c ../Source/umfpack_load_numeric.c + $(MV) -f umfpack_load_numeric.o umfpack_md_load_numeric.o + $(MX) -DDINT -c ../Source/umfpack_save_numeric.c + $(MV) -f umfpack_save_numeric.o umfpack_md_save_numeric.o + $(MX) -DDINT -c ../Source/umfpack_load_symbolic.c + $(MV) -f umfpack_load_symbolic.o umfpack_md_load_symbolic.o + $(MX) -DDINT -c ../Source/umfpack_save_symbolic.c + $(MV) -f umfpack_save_symbolic.o umfpack_md_save_symbolic.o + $(MX) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c + $(MV) -f umf_ltsolve.o umf_mz_lhsolve.o + $(MX) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c + $(MV) -f umf_utsolve.o umf_mz_uhsolve.o + $(MX) -DZINT -DDO_MAP -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_mz_triplet_map_nox.o + $(MX) -DZINT -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_mz_triplet_nomap_x.o + $(MX) -DZINT -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_mz_triplet_nomap_nox.o + $(MX) -DZINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f umf_triplet.o umf_mz_triplet_map_x.o + $(MX) -DZINT -DFIXQ -c ../Source/umf_assemble.c + $(MV) -f umf_assemble.o umf_mz_assemble_fixq.o + $(MX) -DZINT -DDROP -c ../Source/umf_store_lu.c + $(MV) -f umf_store_lu.o umf_mz_store_lu_drop.o + $(MX) -DZINT -c ../Source/umf_assemble.c + $(MV) -f umf_assemble.o umf_mz_assemble.o + $(MX) -DZINT -c ../Source/umf_blas3_update.c + $(MV) -f umf_blas3_update.o umf_mz_blas3_update.o + $(MX) -DZINT -c ../Source/umf_build_tuples.c + $(MV) -f umf_build_tuples.o umf_mz_build_tuples.o + $(MX) -DZINT -c ../Source/umf_create_element.c + $(MV) -f umf_create_element.o umf_mz_create_element.o + $(MX) -DZINT -c ../Source/umf_dump.c + $(MV) -f umf_dump.o umf_mz_dump.o + $(MX) -DZINT -c ../Source/umf_extend_front.c + $(MV) -f umf_extend_front.o umf_mz_extend_front.o + $(MX) -DZINT -c ../Source/umf_garbage_collection.c + $(MV) -f umf_garbage_collection.o umf_mz_garbage_collection.o + $(MX) -DZINT -c ../Source/umf_get_memory.c + $(MV) -f umf_get_memory.o umf_mz_get_memory.o + $(MX) -DZINT -c ../Source/umf_init_front.c + $(MV) -f umf_init_front.o umf_mz_init_front.o + $(MX) -DZINT -c ../Source/umf_kernel.c + $(MV) -f umf_kernel.o umf_mz_kernel.o + $(MX) -DZINT -c ../Source/umf_kernel_init.c + $(MV) -f umf_kernel_init.o umf_mz_kernel_init.o + $(MX) -DZINT -c ../Source/umf_kernel_wrapup.c + $(MV) -f umf_kernel_wrapup.o umf_mz_kernel_wrapup.o + $(MX) -DZINT -c ../Source/umf_local_search.c + $(MV) -f umf_local_search.o umf_mz_local_search.o + $(MX) -DZINT -c ../Source/umf_lsolve.c + $(MV) -f umf_lsolve.o umf_mz_lsolve.o + $(MX) -DZINT -c ../Source/umf_ltsolve.c + $(MV) -f umf_ltsolve.o umf_mz_ltsolve.o + $(MX) -DZINT -c ../Source/umf_mem_alloc_element.c + $(MV) -f umf_mem_alloc_element.o umf_mz_mem_alloc_element.o + $(MX) -DZINT -c ../Source/umf_mem_alloc_head_block.c + $(MV) -f umf_mem_alloc_head_block.o umf_mz_mem_alloc_head_block.o + $(MX) -DZINT -c ../Source/umf_mem_alloc_tail_block.c + $(MV) -f umf_mem_alloc_tail_block.o umf_mz_mem_alloc_tail_block.o + $(MX) -DZINT -c ../Source/umf_mem_free_tail_block.c + $(MV) -f umf_mem_free_tail_block.o umf_mz_mem_free_tail_block.o + $(MX) -DZINT -c ../Source/umf_mem_init_memoryspace.c + $(MV) -f umf_mem_init_memoryspace.o umf_mz_mem_init_memoryspace.o + $(MX) -DZINT -c ../Source/umf_report_vector.c + $(MV) -f umf_report_vector.o umf_mz_report_vector.o + $(MX) -DZINT -c ../Source/umf_row_search.c + $(MV) -f umf_row_search.o umf_mz_row_search.o + $(MX) -DZINT -c ../Source/umf_scale_column.c + $(MV) -f umf_scale_column.o umf_mz_scale_column.o + $(MX) -DZINT -c ../Source/umf_set_stats.c + $(MV) -f umf_set_stats.o umf_mz_set_stats.o + $(MX) -DZINT -c ../Source/umf_solve.c + $(MV) -f umf_solve.o umf_mz_solve.o + $(MX) -DZINT -c ../Source/umf_symbolic_usage.c + $(MV) -f umf_symbolic_usage.o umf_mz_symbolic_usage.o + $(MX) -DZINT -c ../Source/umf_transpose.c + $(MV) -f umf_transpose.o umf_mz_transpose.o + $(MX) -DZINT -c ../Source/umf_tuple_lengths.c + $(MV) -f umf_tuple_lengths.o umf_mz_tuple_lengths.o + $(MX) -DZINT -c ../Source/umf_usolve.c + $(MV) -f umf_usolve.o umf_mz_usolve.o + $(MX) -DZINT -c ../Source/umf_utsolve.c + $(MV) -f umf_utsolve.o umf_mz_utsolve.o + $(MX) -DZINT -c ../Source/umf_valid_numeric.c + $(MV) -f umf_valid_numeric.o umf_mz_valid_numeric.o + $(MX) -DZINT -c ../Source/umf_valid_symbolic.c + $(MV) -f umf_valid_symbolic.o umf_mz_valid_symbolic.o + $(MX) -DZINT -c ../Source/umf_grow_front.c + $(MV) -f umf_grow_front.o umf_mz_grow_front.o + $(MX) -DZINT -c ../Source/umf_start_front.c + $(MV) -f umf_start_front.o umf_mz_start_front.o + $(MX) -DZINT -c ../Source/umf_2by2.c + $(MV) -f umf_2by2.o umf_mz_2by2.o + $(MX) -DZINT -c ../Source/umf_store_lu.c + $(MV) -f umf_store_lu.o umf_mz_store_lu.o + $(MX) -DZINT -c ../Source/umf_scale.c + $(MV) -f umf_scale.o umf_mz_scale.o + $(MX) -DZINT -DWSOLVE -c ../Source/umfpack_solve.c + $(MV) -f umfpack_solve.o umfpack_mz_wsolve.o + $(MX) -DZINT -c ../Source/umfpack_col_to_triplet.c + $(MV) -f umfpack_col_to_triplet.o umfpack_mz_col_to_triplet.o + $(MX) -DZINT -c ../Source/umfpack_defaults.c + $(MV) -f umfpack_defaults.o umfpack_mz_defaults.o + $(MX) -DZINT -c ../Source/umfpack_free_numeric.c + $(MV) -f umfpack_free_numeric.o umfpack_mz_free_numeric.o + $(MX) -DZINT -c ../Source/umfpack_free_symbolic.c + $(MV) -f umfpack_free_symbolic.o umfpack_mz_free_symbolic.o + $(MX) -DZINT -c ../Source/umfpack_get_numeric.c + $(MV) -f umfpack_get_numeric.o umfpack_mz_get_numeric.o + $(MX) -DZINT -c ../Source/umfpack_get_lunz.c + $(MV) -f umfpack_get_lunz.o umfpack_mz_get_lunz.o + $(MX) -DZINT -c ../Source/umfpack_get_symbolic.c + $(MV) -f umfpack_get_symbolic.o umfpack_mz_get_symbolic.o + $(MX) -DZINT -c ../Source/umfpack_get_determinant.c + $(MV) -f umfpack_get_determinant.o umfpack_mz_get_determinant.o + $(MX) -DZINT -c ../Source/umfpack_numeric.c + $(MV) -f umfpack_numeric.o umfpack_mz_numeric.o + $(MX) -DZINT -c ../Source/umfpack_qsymbolic.c + $(MV) -f umfpack_qsymbolic.o umfpack_mz_qsymbolic.o + $(MX) -DZINT -c ../Source/umfpack_report_control.c + $(MV) -f umfpack_report_control.o umfpack_mz_report_control.o + $(MX) -DZINT -c ../Source/umfpack_report_info.c + $(MV) -f umfpack_report_info.o umfpack_mz_report_info.o + $(MX) -DZINT -c ../Source/umfpack_report_matrix.c + $(MV) -f umfpack_report_matrix.o umfpack_mz_report_matrix.o + $(MX) -DZINT -c ../Source/umfpack_report_numeric.c + $(MV) -f umfpack_report_numeric.o umfpack_mz_report_numeric.o + $(MX) -DZINT -c ../Source/umfpack_report_perm.c + $(MV) -f umfpack_report_perm.o umfpack_mz_report_perm.o + $(MX) -DZINT -c ../Source/umfpack_report_status.c + $(MV) -f umfpack_report_status.o umfpack_mz_report_status.o + $(MX) -DZINT -c ../Source/umfpack_report_symbolic.c + $(MV) -f umfpack_report_symbolic.o umfpack_mz_report_symbolic.o + $(MX) -DZINT -c ../Source/umfpack_report_triplet.c + $(MV) -f umfpack_report_triplet.o umfpack_mz_report_triplet.o + $(MX) -DZINT -c ../Source/umfpack_report_vector.c + $(MV) -f umfpack_report_vector.o umfpack_mz_report_vector.o + $(MX) -DZINT -c ../Source/umfpack_solve.c + $(MV) -f umfpack_solve.o umfpack_mz_solve.o + $(MX) -DZINT -c ../Source/umfpack_symbolic.c + $(MV) -f umfpack_symbolic.o umfpack_mz_symbolic.o + $(MX) -DZINT -c ../Source/umfpack_transpose.c + $(MV) -f umfpack_transpose.o umfpack_mz_transpose.o + $(MX) -DZINT -c ../Source/umfpack_triplet_to_col.c + $(MV) -f umfpack_triplet_to_col.o umfpack_mz_triplet_to_col.o + $(MX) -DZINT -c ../Source/umfpack_scale.c + $(MV) -f umfpack_scale.o umfpack_mz_scale.o + $(MX) -DZINT -c ../Source/umfpack_load_numeric.c + $(MV) -f umfpack_load_numeric.o umfpack_mz_load_numeric.o + $(MX) -DZINT -c ../Source/umfpack_save_numeric.c + $(MV) -f umfpack_save_numeric.o umfpack_mz_save_numeric.o + $(MX) -DZINT -c ../Source/umfpack_load_symbolic.c + $(MV) -f umfpack_load_symbolic.o umfpack_mz_load_symbolic.o + $(MX) -DZINT -c ../Source/umfpack_save_symbolic.c + $(MV) -f umfpack_save_symbolic.o umfpack_mz_save_symbolic.o + $(MX) -c ../Source/umfpack_timer.c + $(MV) -f umfpack_timer.o umfpack_m_timer.o + $(MX) -c ../Source/umfpack_tictoc.c + $(MV) -f umfpack_tictoc.o umfpack_m_tictoc.o + $(MX) -DDINT -c ../../AMD/Source/amd_aat.c + $(MV) -f amd_aat.o amd_m_aat.o + $(MX) -DDINT -c ../../AMD/Source/amd_1.c + $(MV) -f amd_1.o amd_m_1.o + $(MX) -DDINT -c ../../AMD/Source/amd_2.c + $(MV) -f amd_2.o amd_m_2.o + $(MX) -DDINT -c ../../AMD/Source/amd_dump.c + $(MV) -f amd_dump.o amd_m_dump.o + $(MX) -DDINT -c ../../AMD/Source/amd_postorder.c + $(MV) -f amd_postorder.o amd_m_postorder.o + $(MX) -DDINT -c ../../AMD/Source/amd_post_tree.c + $(MV) -f amd_post_tree.o amd_m_post_tree.o + $(MX) -DDINT -c ../../AMD/Source/amd_defaults.c + $(MV) -f amd_defaults.o amd_m_defaults.o + $(MX) -DDINT -c ../../AMD/Source/amd_order.c + $(MV) -f amd_order.o amd_m_order.o + $(MX) -DDINT -c ../../AMD/Source/amd_control.c + $(MV) -f amd_control.o amd_m_control.o + $(MX) -DDINT -c ../../AMD/Source/amd_info.c + $(MV) -f amd_info.o amd_m_info.o + $(MX) -DDINT -c ../../AMD/Source/amd_valid.c + $(MV) -f amd_valid.o amd_m_valid.o + $(MX) -output umfpack umfpackmex.c \ + umf_m_analyze.o umf_m_apply_order.o umf_m_colamd.o umf_m_free.o \ + umf_m_fsize.o umf_m_is_permutation.o umf_m_malloc.o \ + umf_m_realloc.o umf_m_report_perm.o umf_m_singletons.o \ + umf_md_lhsolve.o umf_md_uhsolve.o umf_md_triplet_map_nox.o \ + umf_md_triplet_nomap_x.o umf_md_triplet_nomap_nox.o \ + umf_md_triplet_map_x.o umf_md_assemble_fixq.o \ + umf_md_store_lu_drop.o umf_md_assemble.o umf_md_blas3_update.o \ + umf_md_build_tuples.o umf_md_create_element.o umf_md_dump.o \ + umf_md_extend_front.o umf_md_garbage_collection.o \ + umf_md_get_memory.o umf_md_init_front.o umf_md_kernel.o \ + umf_md_kernel_init.o umf_md_kernel_wrapup.o umf_md_local_search.o \ + umf_md_lsolve.o umf_md_ltsolve.o umf_md_mem_alloc_element.o \ + umf_md_mem_alloc_head_block.o umf_md_mem_alloc_tail_block.o \ + umf_md_mem_free_tail_block.o umf_md_mem_init_memoryspace.o \ + umf_md_report_vector.o umf_md_row_search.o umf_md_scale_column.o \ + umf_md_set_stats.o umf_md_solve.o umf_md_symbolic_usage.o \ + umf_md_transpose.o umf_md_tuple_lengths.o umf_md_usolve.o \ + umf_md_utsolve.o umf_md_valid_numeric.o umf_md_valid_symbolic.o \ + umf_md_grow_front.o umf_md_start_front.o umf_md_2by2.o \ + umf_md_store_lu.o umf_md_scale.o umfpack_md_wsolve.o \ + umfpack_md_col_to_triplet.o umfpack_md_defaults.o \ + umfpack_md_free_numeric.o umfpack_md_free_symbolic.o \ + umfpack_md_get_numeric.o umfpack_md_get_lunz.o \ + umfpack_md_get_symbolic.o umfpack_md_get_determinant.o \ + umfpack_md_numeric.o \ + umfpack_md_qsymbolic.o umfpack_md_report_control.o \ + umfpack_md_report_info.o umfpack_md_report_matrix.o \ + umfpack_md_report_numeric.o umfpack_md_report_perm.o \ + umfpack_md_report_status.o umfpack_md_report_symbolic.o \ + umfpack_md_report_triplet.o umfpack_md_report_vector.o \ + umfpack_md_solve.o umfpack_md_symbolic.o umfpack_md_transpose.o \ + umfpack_md_triplet_to_col.o umfpack_md_scale.o \ + umfpack_md_load_numeric.o umfpack_md_save_numeric.o \ + umfpack_md_load_symbolic.o umfpack_md_save_symbolic.o \ + umf_mz_lhsolve.o umf_mz_uhsolve.o umf_mz_triplet_map_nox.o \ + umf_mz_triplet_nomap_x.o umf_mz_triplet_nomap_nox.o \ + umf_mz_triplet_map_x.o umf_mz_assemble_fixq.o \ + umf_mz_store_lu_drop.o umf_mz_assemble.o umf_mz_blas3_update.o \ + umf_mz_build_tuples.o umf_mz_create_element.o umf_mz_dump.o \ + umf_mz_extend_front.o umf_mz_garbage_collection.o \ + umf_mz_get_memory.o umf_mz_init_front.o umf_mz_kernel.o \ + umf_mz_kernel_init.o umf_mz_kernel_wrapup.o umf_mz_local_search.o \ + umf_mz_lsolve.o umf_mz_ltsolve.o umf_mz_mem_alloc_element.o \ + umf_mz_mem_alloc_head_block.o umf_mz_mem_alloc_tail_block.o \ + umf_mz_mem_free_tail_block.o umf_mz_mem_init_memoryspace.o \ + umf_mz_report_vector.o umf_mz_row_search.o umf_mz_scale_column.o \ + umf_mz_set_stats.o umf_mz_solve.o umf_mz_symbolic_usage.o \ + umf_mz_transpose.o umf_mz_tuple_lengths.o umf_mz_usolve.o \ + umf_mz_utsolve.o umf_mz_valid_numeric.o umf_mz_valid_symbolic.o \ + umf_mz_grow_front.o umf_mz_start_front.o umf_mz_2by2.o \ + umf_mz_store_lu.o umf_mz_scale.o umfpack_mz_wsolve.o \ + umfpack_mz_col_to_triplet.o umfpack_mz_defaults.o \ + umfpack_mz_free_numeric.o umfpack_mz_free_symbolic.o \ + umfpack_mz_get_numeric.o umfpack_mz_get_lunz.o \ + umfpack_mz_get_symbolic.o umfpack_mz_get_determinant.o \ + umfpack_mz_numeric.o \ + umfpack_mz_qsymbolic.o umfpack_mz_report_control.o \ + umfpack_mz_report_info.o umfpack_mz_report_matrix.o \ + umfpack_mz_report_numeric.o umfpack_mz_report_perm.o \ + umfpack_mz_report_status.o umfpack_mz_report_symbolic.o \ + umfpack_mz_report_triplet.o umfpack_mz_report_vector.o \ + umfpack_mz_solve.o umfpack_mz_symbolic.o umfpack_mz_transpose.o \ + umfpack_mz_triplet_to_col.o umfpack_mz_scale.o \ + umfpack_mz_load_numeric.o umfpack_mz_save_numeric.o \ + umfpack_mz_load_symbolic.o umfpack_mz_save_symbolic.o \ + umfpack_m_timer.o umfpack_m_tictoc.o \ + amd_m_aat.o amd_m_1.o amd_m_2.o amd_m_dump.o \ + amd_m_postorder.o amd_m_post_tree.o amd_m_defaults.o amd_m_order.o \ + amd_m_control.o amd_m_info.o amd_m_valid.o + +luflop: luflopmex.c + $(MX) -output luflop luflopmex.c + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) *.mex* *.dll diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/lcc_lib/lapacksyms.def b/liboctave/UMFPACK/UMFPACK/MATLAB/lcc_lib/lapacksyms.def new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/lcc_lib/lapacksyms.def @@ -0,0 +1,718 @@ +LIBRARY liblapack.dll +EXPORTS +dasum +daxpy +dbdsdc +dbdsqr +dcopy +ddisna +ddot +dgbbrd +dgbcon +dgbequ +dgbmv +dgbrfs +dgbsv +dgbsvx +dgbtf2 +dgbtrf +dgbtrs +dgebak +dgebal +dgebd2 +dgebrd +dgecon +dgeequ +dgees +dgeesx +dgeev +dgeevx +dgegs +dgegv +dgehd2 +dgehrd +dgelq2 +dgelqf +dgels +dgelsd +dgelss +dgelsx +dgelsy +dgemm +dgemv +dgeql2 +dgeqlf +dgeqp3 +dgeqpf +dgeqr2 +dgeqrf +dger +dgerfs +dgerq2 +dgerqf +dgesc2 +dgesdd +dgesv +dgesvd +dgesvx +dgetc2 +dgetf2 +dgetrf +dgetri +dgetrs +dggbak +dggbal +dgges +dggesx +dggev +dggevx +dggglm +dgghrd +dgglse +dggqrf +dggrqf +dggsvd +dggsvp +dgtcon +dgtrfs +dgtsv +dgtsvx +dgttrf +dgttrs +dgtts2 +dhgeqz +dhsein +dhseqr +dlabad +dlabrd +dlacon +dlacpy +dladiv +dlae2 +dlaebz +dlaed0 +dlaed1 +dlaed2 +dlaed3 +dlaed4 +dlaed5 +dlaed6 +dlaed7 +dlaed8 +dlaed9 +dlaeda +dlaein +dlaev2 +dlaexc +dlag2 +dlags2 +dlagtf +dlagtm +dlagts +dlagv2 +dlahqr +dlahrd +dlaic1 +dlaln2 +dlals0 +dlalsa +dlalsd +dlamch +dlamrg +dlangb +dlange +dlangt +dlanhs +dlansb +dlansp +dlanst +dlansy +dlantb +dlantp +dlantr +dlanv2 +dlapll +dlapmt +dlapy2 +dlapy3 +dlaqgb +dlaqge +dlaqp2 +dlaqps +dlaqsb +dlaqsp +dlaqsy +dlaqtr +dlar1v +dlar2v +dlarf +dlarfb +dlarfg +dlarft +dlarfx +dlargv +dlarnv +dlarrb +dlarre +dlarrf +dlarrv +dlartg +dlartv +dlaruv +dlarz +dlarzb +dlarzt +dlas2 +dlascl +dlasd0 +dlasd1 +dlasd2 +dlasd3 +dlasd4 +dlasd5 +dlasd6 +dlasd7 +dlasd8 +dlasd9 +dlasda +dlasdq +dlasdt +dlaset +dlasq1 +dlasq2 +dlasq3 +dlasq4 +dlasq5 +dlasq6 +dlasr +dlasrt +dlassq +dlasv2 +dlaswp +dlasy2 +dlasyf +dlatbs +dlatdf +dlatps +dlatrd +dlatrs +dlatrz +dlatzm +dlauu2 +dlauum +dnrm2 +dopgtr +dopmtr +dorg2l +dorg2r +dorgbr +dorghr +dorgl2 +dorglq +dorgql +dorgqr +dorgr2 +dorgrq +dorgtr +dorm2l +dorm2r +dormbr +dormhr +dorml2 +dormlq +dormql +dormqr +dormr2 +dormr3 +dormrq +dormrz +dormtr +dpbcon +dpbequ +dpbrfs +dpbstf +dpbsv +dpbsvx +dpbtf2 +dpbtrf +dpbtrs +dpocon +dpoequ +dporfs +dposv +dposvx +dpotf2 +dpotrf +dpotri +dpotrs +dppcon +dppequ +dpprfs +dppsv +dppsvx +dpptrf +dpptri +dpptrs +dptcon +dpteqr +dptrfs +dptsv +dptsvx +dpttrf +dpttrs +dptts2 +drot +drotg +drscl +dsbev +dsbevd +dsbevx +dsbgst +dsbgv +dsbgvd +dsbgvx +dsbmv +dsbtrd +dscal +dspcon +dspev +dspevd +dspevx +dspgst +dspgv +dspgvd +dspgvx +dspmv +dspr +dspr2 +dsprfs +dspsv +dspsvx +dsptrd +dsptrf +dsptri +dsptrs +dstebz +dstedc +dstegr +dstein +dsteqr +dsterf +dstev +dstevd +dstevr +dstevx +dswap +dsycon +dsyev +dsyevd +dsyevr +dsyevx +dsygs2 +dsygst +dsygv +dsygvd +dsygvx +dsymm +dsymv +dsyr +dsyr2 +dsyr2k +dsyrfs +dsyrk +dsysv +dsysvx +dsytd2 +dsytf2 +dsytrd +dsytrf +dsytri +dsytrs +dtbcon +dtbmv +dtbrfs +dtbsv +dtbtrs +dtgevc +dtgex2 +dtgexc +dtgsen +dtgsja +dtgsna +dtgsy2 +dtgsyl +dtpcon +dtpmv +dtprfs +dtpsv +dtptri +dtptrs +dtrcon +dtrevc +dtrexc +dtrmm +dtrmv +dtrrfs +dtrsen +dtrsm +dtrsna +dtrsv +dtrsyl +dtrti2 +dtrtri +dtrtrs +dtzrqf +dtzrzf +dzasum +dznrm2 +dzsum1 +idamax +ieeeck +ilaenv +izamax +izmax1 +lsame +lsamen +xerbla +zaxpy +zbdsqr +zcopy +zdotc +zdotu +zdrot +zdrscl +zdscal +zgbbrd +zgbcon +zgbequ +zgbmv +zgbrfs +zgbsv +zgbsvx +zgbtf2 +zgbtrf +zgbtrs +zgebak +zgebal +zgebd2 +zgebrd +zgecon +zgeequ +zgees +zgeesx +zgeev +zgeevx +zgegs +zgegv +zgehd2 +zgehrd +zgelq2 +zgelqf +zgels +zgelsd +zgelss +zgelsx +zgelsy +zgemm +zgemv +zgeql2 +zgeqlf +zgeqp3 +zgeqpf +zgeqr2 +zgeqrf +zgerc +zgerfs +zgerq2 +zgerqf +zgeru +zgesc2 +zgesdd +zgesv +zgesvd +zgesvx +zgetc2 +zgetf2 +zgetrf +zgetri +zgetrs +zggbak +zggbal +zgges +zggesx +zggev +zggevx +zggglm +zgghrd +zgglse +zggqrf +zggrqf +zggsvd +zggsvp +zgtcon +zgtrfs +zgtsv +zgtsvx +zgttrf +zgttrs +zgtts2 +zhbev +zhbevd +zhbevx +zhbgst +zhbgv +zhbgvd +zhbgvx +zhbmv +zhbtrd +zhecon +zheev +zheevd +zheevr +zheevx +zhegs2 +zhegst +zhegv +zhegvd +zhegvx +zhemm +zhemv +zher +zher2 +zher2k +zherfs +zherk +zhesv +zhesvx +zhetd2 +zhetf2 +zhetrd +zhetrf +zhetri +zhetrs +zhgeqz +zhpcon +zhpev +zhpevd +zhpevx +zhpgst +zhpgv +zhpgvd +zhpgvx +zhpmv +zhpr +zhpr2 +zhprfs +zhpsv +zhpsvx +zhptrd +zhptrf +zhptri +zhptrs +zhsein +zhseqr +zlabrd +zlacgv +zlacon +zlacp2 +zlacpy +zlacrm +zlacrt +zladiv +zlaed0 +zlaed7 +zlaed8 +zlaein +zlaesy +zlaev2 +zlags2 +zlagtm +zlahef +zlahqr +zlahrd +zlaic1 +zlals0 +zlalsa +zlalsd +zlangb +zlange +zlangt +zlanhb +zlanhe +zlanhp +zlanhs +zlanht +zlansb +zlansp +zlansy +zlantb +zlantp +zlantr +zlapll +zlapmt +zlaqgb +zlaqge +zlaqhb +zlaqhe +zlaqhp +zlaqp2 +zlaqps +zlaqsb +zlaqsp +zlaqsy +zlar1v +zlar2v +zlarcm +zlarf +zlarfb +zlarfg +zlarft +zlarfx +zlargv +zlarnv +zlarrv +zlartg +zlartv +zlarz +zlarzb +zlarzt +zlascl +zlaset +zlasr +zlassq +zlaswp +zlasyf +zlatbs +zlatdf +zlatps +zlatrd +zlatrs +zlatrz +zlatzm +zlauu2 +zlauum +zpbcon +zpbequ +zpbrfs +zpbstf +zpbsv +zpbsvx +zpbtf2 +zpbtrf +zpbtrs +zpocon +zpoequ +zporfs +zposv +zposvx +zpotf2 +zpotrf +zpotri +zpotrs +zppcon +zppequ +zpprfs +zppsv +zppsvx +zpptrf +zpptri +zpptrs +zptcon +zpteqr +zptrfs +zptsv +zptsvx +zpttrf +zpttrs +zptts2 +zrot +zrotg +zscal +zspcon +zspmv +zspr +zsprfs +zspsv +zspsvx +zsptrf +zsptri +zsptrs +zstedc +zstegr +zstein +zsteqr +zswap +zsycon +zsymm +zsymv +zsyr +zsyr2k +zsyrfs +zsyrk +zsysv +zsysvx +zsytf2 +zsytrf +zsytri +zsytrs +ztbcon +ztbmv +ztbrfs +ztbsv +ztbtrs +ztgevc +ztgex2 +ztgexc +ztgsen +ztgsja +ztgsna +ztgsy2 +ztgsyl +ztpcon +ztpmv +ztprfs +ztpsv +ztptri +ztptrs +ztrcon +ztrevc +ztrexc +ztrmm +ztrmv +ztrrfs +ztrsen +ztrsm +ztrsna +ztrsv +ztrsyl +ztrti2 +ztrtri +ztrtrs +ztzrqf +ztzrzf +zung2l +zung2r +zungbr +zunghr +zungl2 +zunglq +zungql +zungqr +zungr2 +zungrq +zungtr +zunm2l +zunm2r +zunmbr +zunmhr +zunml2 +zunmlq +zunmql +zunmqr +zunmr2 +zunmr3 +zunmrq +zunmrz +zunmtr +zupgtr +zupmtr diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/lcc_lib/libmwlapack.lib b/liboctave/UMFPACK/UMFPACK/MATLAB/lcc_lib/libmwlapack.lib new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ba94c1bae40289f8ffd3c21c68dc5e471682bc74 GIT binary patch literal 466678 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 S*QB43ZddBn{!UJ^O#MIY#SVS| diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/lu_normest.m b/liboctave/UMFPACK/UMFPACK/MATLAB/lu_normest.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/lu_normest.m @@ -0,0 +1,106 @@ +function rho = lu_normest (A, L, U) +% LU_NORMEST: estimate the 1-norm of A-L*U without computing L*U +% +% Usage: +% +% rho = lu_normest (A, L, U) +% +% which estimates the computation of the 1-norm: +% +% rho = norm (A-L*U, 1) +% +% Authors: William W. Hager, Math Dept., Univ. of Florida +% Timothy A. Davis, CISE Dept., Univ. of Florida +% Gainesville, FL, 32611, USA. +% based on normest1, contributed on November, 1997 +% +% This code can be quite easily adapted to estimate the 1-norm of any +% matrix E, where E itself is dense or not explicitly represented, but the +% computation of E (and E') times a vector is easy. In this case, our matrix +% of interest is: +% +% E = A-L*U +% +% That is, L*U is the LU factorization of A, where A, L and U +% are sparse. This code works for dense matrices A and L too, +% but it would not be needed in that case, since E is easy to compute +% explicitly. For sparse A, L, and U, computing E explicitly would be quite +% expensive, and thus normest (A-L*U) would be prohibitive. +% +% For a detailed description, see Davis, T. A. and Hager, W. W., +% Modifying a sparse Cholesky factorization, SIAM J. Matrix Analysis and +% Applications, 1999, vol. 20, no. 3, 606-627. + +% The three places that the matrix-vector multiply E*x is used are highlighted. +% Note that E is never formed explicity. + +[m n] = size (A) ; + +if (m ~= n) + % pad A, L, and U with zeros so that they are all square + if (m < n) + U = [ U ; (sparse (n-m,n)) ] ; + L = [ L , (sparse (m,n-m)) ; (sparse (n-m,n)) ] ; + A = [ A ; (sparse (n-m,n)) ] ; + else + U = [ U , (sparse (n,m-n)) ; (sparse (m-n,m)) ] ; + L = [ L , (sparse (m,m-n)) ] ; + A = [ A , (sparse (m,m-n)) ] ; + end +end + +[m n] = size (A) ; + +notvisited = ones (m, 1) ; % nonvisited(j) is zero if j is visited, 1 otherwise +rho = 0 ; % the global rho + +At = A' ; +Lt = L' ; + +for trial = 1:3 % { + + x = notvisited ./ sum (notvisited) ; + rho1 = 0 ; % the current rho for this trial + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Ex1 = (A*x) - L*(U*x) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + rho2 = norm (Ex1, 1) ; + + while rho2 > rho1 % { + + rho1 = rho2 ; + y = 2*(Ex1 >= 0) - 1 ; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE z = E'*y EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + z = (A'*y) - U'*(L'*y) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + [zj, j] = max (abs (z .* notvisited)) ; + j = j (1) ; + if (abs (z (j)) > z'*x) % { + x = zeros (m, 1) ; + x (j) = 1 ; + notvisited (j) = 0 ; + else % } { + break ; + end % } + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Ex1 = (A*x) - L*(U*x) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + rho2 = norm (Ex1, 1) ; + + end % } + + rho = max (rho, rho1) ; + +end % } diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/luflop.m b/liboctave/UMFPACK/UMFPACK/MATLAB/luflop.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/luflop.m @@ -0,0 +1,24 @@ +function f = luflop (L, U) +%LUFLOP +% +% f = luflop (L, U) +% +% Given an LU factorization, compute how many flops took to compute it. This +% is the same as (assuming U has a zero-free diagonal): +% +% Lnz = full (sum (spones (L))) - 1 ; +% Unz = full (sum (spones (U')))' - 1 ; +% f = 2*Lnz*Unz + sum (Lnz) ; +% +% except that no extra workspace is allocated for spones (L) and spones (U). +% L and U must be sparse. +% +% Note: the above expression has a subtle undercount when exact numerical +% cancelation occurs. Try [L,U,P] = lu (sparse (ones (10))) and then +% luflop (L,U). + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +help luflop +error ('luflop mexFunction not found! Use umfpack_make to compile luflop.') ; diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/luflopmex.c b/liboctave/UMFPACK/UMFPACK/MATLAB/luflopmex.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/luflopmex.c @@ -0,0 +1,121 @@ +/* ========================================================================== */ +/* === luflop mexFunction ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + f = luflop (L, U) ; + + Given L and U, compute: + + Lnz = full (sum (spones (L))) - 1 ; + Unz = full (sum (spones (U')))' - 1 ; + f = 2*Lnz*Unz + sum (Lnz) ; + + without allocating O (lunz) space. + +*/ + +#include "mex.h" +#include "matrix.h" + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +void mexFunction +( + int nlhs, /* number of left-hand sides */ + mxArray *plhs [ ], /* left-hand side matrices */ + int nrhs, /* number of right--hand sides */ + const mxArray *prhs [ ] /* right-hand side matrices */ +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double flop_count ; + double *pflop ; + int *Lp, *Li, *Up, *Ui, *Unz, n, k, row, col, p, Lnz_k, Unz_k ; + mxArray *Lmatrix, *Umatrix ; + + /* ---------------------------------------------------------------------- */ + /* get inputs L, U */ + /* ---------------------------------------------------------------------- */ + + if (nrhs != 2) + { + mexErrMsgTxt ("Usage: f = luflop (L, U)") ; + } + + Lmatrix = (mxArray *) prhs [0] ; + Umatrix = (mxArray *) prhs [1] ; + + n = mxGetM (Lmatrix) ; + if (n != mxGetN (Lmatrix) || n != mxGetM (Umatrix) || n != mxGetN (Umatrix)) + { + mexErrMsgTxt ("Usage: f = luflop (L, U) ; L and U must be square") ; + } + + if (!mxIsSparse (Lmatrix) || !mxIsSparse (Umatrix)) + { + mexErrMsgTxt ("Usage: f = luflop (L, U) ; L and U must be sparse") ; + } + + Lp = mxGetJc (Lmatrix) ; + Li = mxGetIr (Lmatrix) ; + + Up = mxGetJc (Umatrix) ; + Ui = mxGetIr (Umatrix) ; + + Unz = (int *) mxMalloc (n * sizeof (int)) ; + + /* ---------------------------------------------------------------------- */ + /* count the nonzeros in each row of U */ + /* ---------------------------------------------------------------------- */ + + for (row = 0 ; row < n ; row++) + { + Unz [row] = 0 ; + } + for (col = 0 ; col < n ; col++) + { + for (p = Up [col] ; p < Up [col+1] ; p++) + { + row = Ui [p] ; + Unz [row]++ ; + } + } + + /* ---------------------------------------------------------------------- */ + /* count the flops */ + /* ---------------------------------------------------------------------- */ + + flop_count = 0.0 ; + for (k = 0 ; k < n ; k++) + { + /* off-diagonal nonzeros in column k of L: */ + Lnz_k = Lp [k+1] - Lp [k] - 1 ; + Unz_k = Unz [k] - 1 ; + flop_count += (2 * Lnz_k * Unz_k) + Lnz_k ; + } + + /* ---------------------------------------------------------------------- */ + /* return the result */ + /* ---------------------------------------------------------------------- */ + + plhs [0] = mxCreateDoubleMatrix (1, 1, mxREAL) ; + pflop = mxGetPr (plhs [0]) ; + pflop [0] = flop_count ; +} + diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack.m @@ -0,0 +1,44 @@ +function [out1, out2, out3, out4, out5] = umfpack (in1, in2, in3, in4, in5) +% UMFPACK v4.4 is a MATLAB mexFunction for solving sparse linear systems. +% +% UMFPACK v4.4: | MATLAB approximate equivalent: +% --------------------------------------------------------------------- +% x = umfpack (A, '\', b) ; | x = A \ b +% | +% x = umfpack (b, '/', A) ; | x = b / A +% | +% [L,U,P,Q] = umfpack (A) ; | [m,n] = size (A) ; +% | I = speye (n) ; +% | Q = I (:, colamd (A)) ; +% | [L,U,P] = lu (A*Q) ; +% | +% [L,U,P,Q,R] = umfpack (A) ; | [m,n] = size (A) ; +% | I = speye (n) ; +% | Q = I (:, colamd (A)) ; +% | r = full (sum (abs (A), 2)) ; +% | r (find (r == 0)) = 1 ; +% | R = spdiags (r, 0, m, m) ; +% | [L,U,P] = lu ((R\A)*Q) ; +% | +% [P,Q,F,C] = umfpack (A, 'symbolic') | [m,n] = size (A) ; +% | I = speye (n) ; +% | Q = I (:, colamd (A)) ; +% | [count,h,parent,post] = ... +% | symbfact (A*Q, 'col') ; +% +% A must be sparse. It can be complex, singular, and/or rectangular. A must be +% square for '/' or '\'. b must be a full real or complex vector. For +% [L,U,P,Q,R] = umfpack (A), the factorization is L*U = P*(R\A)*Q. If A has a +% mostly symmetric nonzero pattern, then replace "colamd" with "amd" in the +% MATLAB-equivalent column in the table above. Type umfpack_details for more +% information. +% +% See also: lu_normest, colamd, amd. +% To use UMFPACK for an arbitrary b, see umfpack_solve. + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +help umfpack +error ('umfpack mexFunction not found! Use umfpack_make to compile umfpack.') ; + diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_btf.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_btf.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_btf.m @@ -0,0 +1,129 @@ +function x = umfpack_btf (A, b, Control) +% UMFPACK_BTF +% +% x = umfpack_btf (A, b, Control) +% +% solve Ax=b by first permuting the matrix A to block triangular form via dmperm +% and then using UMFPACK to factorize each diagonal block. Adjacent 1-by-1 +% blocks are merged into a single upper triangular block, and solved via +% MATLAB's \ operator. The Control parameter is optional (Type umfpack_details +% and umfpack_report for details on its use). A must be square. +% +% See also: umfpack, umfpack_factorize, umfpack_details, dmperm + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +if (nargin < 2) + help umfpack_btf + error ('Usage: x = umfpack_btf (A, b, Control)') ; +end + +[m n] = size (A) ; +if (m ~= n) + help umfpack_btf + error ('umfpack_btf: A must be square') ; +end +[m1 n1] = size (b) ; +if (m1 ~= n) + help umfpack_btf + error ('umfpack_btf: b has the wrong dimensions') ; +end + +if (nargin < 3) + Control = umfpack ; +end + +%------------------------------------------------------------------------------- +% find the block triangular form +%------------------------------------------------------------------------------- + +[p,q,r] = dmperm (A) ; +nblocks = length (r) - 1 ; + +%------------------------------------------------------------------------------- +% solve the system +%------------------------------------------------------------------------------- + +if (nblocks == 1 | sprank (A) < n) + + %--------------------------------------------------------------------------- + % matrix is irreducible or structurally singular + %--------------------------------------------------------------------------- + + x = umfpack_solve (A, '\', b, Control) ; + +else + + %--------------------------------------------------------------------------- + % A (p,q) is in block triangular form + %--------------------------------------------------------------------------- + + b = b (p,:) ; + A = A (p,q) ; + x = zeros (size (b)) ; + + %--------------------------------------------------------------------------- + % merge adjacent singletons into a single upper triangular block + %--------------------------------------------------------------------------- + + [r, nblocks, is_triangular] = merge_singletons (r) ; + + %--------------------------------------------------------------------------- + % solve the system: x (q) = A\b + %--------------------------------------------------------------------------- + + for k = nblocks:-1:1 + + % get the kth block + k1 = r (k) ; + k2 = r (k+1) - 1 ; + + % solve the system + x (k1:k2,:) = solver (A (k1:k2, k1:k2), b (k1:k2,:), ... + is_triangular (k), Control) ; + + % off-diagonal block back substitution + b (1:k1-1,:) = b (1:k1-1,:) - A (1:k1-1, k1:k2) * x (k1:k2,:) ; + + end + + x (q,:) = x ; + +end + +%------------------------------------------------------------------------------- +% merge_singletons +%------------------------------------------------------------------------------- + +function [r, nblocks, is_triangular] = merge_singletons (r) +% +% Given r from [p,q,r] = dmperm (A), where A is square, return a modified r that +% reflects the merger of adjacent singletons into a single upper triangular +% block. is_triangular (k) is 1 if the kth block is upper triangular. nblocks +% is the number of new blocks. + +nblocks = length (r) - 1 ; +bsize = r (2:nblocks+1) - r (1:nblocks) ; +t = [0 (bsize == 1)] ; +z = (t (1:nblocks) == 0 & t (2:nblocks+1) == 1) | t (2:nblocks+1) == 0 ; +y = [(find (z)) nblocks+1] ; +r = r (y) ; +nblocks = length (y) - 1 ; +is_triangular = y (2:nblocks+1) - y (1:nblocks) > 1 ; + +%------------------------------------------------------------------------------- +% solve Ax=b, but check for small and/or triangular systems +%------------------------------------------------------------------------------- + +function x = solver (A, b, is_triangular, Control) +if (is_triangular) + % back substitution only + x = A \ b ; +elseif (size (A,1) < 4) + % a very small matrix, solve it as a dense linear system + x = full (A) \ b ; +else + % solve it as a sparse linear system + x = umfpack_solve (A, '\', b, Control) ; +end diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m @@ -0,0 +1,202 @@ +function umfpack_demo +% UMFPACK DEMO +% +% A demo of UMFPACK for MATLAB. +% +% See also umfpack, umfpack_make, umfpack_details, umfpack_report, +% and umfpack_simple. + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +%------------------------------------------------------------------------------- +% get default control parameters +%------------------------------------------------------------------------------- + +control = umfpack ; +fprintf ('\nEnter the printing level for UMFPACK''s output statistics:\n') ; +fprintf ('0: none, 1: errors only, 2: statistics, 4: print some of outputs\n') ; +c = input ('5: print all output [default is 1]: ') ; +if (isempty (c)) + c = 1 ; +end +control (1) = c ; + +%------------------------------------------------------------------------------- +% solve a simple system +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Factor and solve a small system, Ax=b, using default parameters\n') ; +if (control (1) > 1) + fprintf ('(except for verbose printing enabled)\n') ; +end + +load west0067 +A = Problem.A ; +n = size (A, 1) ; +b = rand (n, 1) ; + +fprintf ('Solving Ax=b via UMFPACK:\n') ; +[xu, info] = umfpack (A, '\', b, control) ; +x = xu ; + +fprintf ('Solving Ax=b via MATLAB:\n') ; +xm = A\b ; +x = xm ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% spy the results +%------------------------------------------------------------------------------- + +figure (1) +clf + +subplot (2,3,1) +spy (A) +title ('The matrix A') ; + +subplot (2,3,2) +[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ; +treeplot (Fr (1:end-1,2)') ; +title ('Supernodal column elimination tree') ; + +subplot (2,3,3) +spy (P1 * A * Q1) +title ('A, with initial row and column order') ; + +subplot (2,3,4) +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nFactorizing [L, U, P, Q, R] = umfpack (A)\n') ; +[L, U, P, Q, R] = umfpack (A) ; +spy (P*A*Q) +title ('A, with final row/column order') ; + +fprintf ('\nP * (R\\A) * Q - L*U should be zero:\n') ; +fprintf ('norm (P*(R\\A)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... + norm (P * (R\A) * Q - L*U, 1), lu_normest (P * (R\A) * Q, L, U)) ; + +fprintf ('\nSolution to Ax=b via UMFPACK factorization:\n') ; +fprintf ('x = Q * (U \\ (L \\ (P * (R \\ b))))\n') ; +xu = Q * (U \ (L \ (P * (R \ b)))) ; +x = xu ; + +fprintf ('\nUMFPACK flop count: %d\n', luflop (L, U)) ; + +subplot (2,3,5) +spy (spones (L) + spones (U)) +title ('UMFPACK LU factors') ; + +subplot (2,3,6) +fprintf ('\nFactorizing [L, U, P] = lu (A (:, q))\n') ; +fprintf ('If you are using a version of MATLAB prior to V6.0, then the\n') ; +fprintf ('following statement (q = colamd (A)) may fail. Either download\n'); +fprintf ('colamd from http://www.cise.ufl.edu/research/sparse, upgrade to\n') ; +fprintf ('MATLAB V6.0 or later, or replace the statement with\n') ; +fprintf ('q = colmmd (A) ;\n') ; +try + q = colamd (A) ; +catch + fprintf ('\n *** colamd not found, using colmmd instead *** \n') ; + q = colmmd (A) ; +end +[L, U, P] = lu (A (:,q)) ; +spy (spones (L) + spones (U)) +title ('MATLAB LU factors') ; + +fprintf ('\nSolution to Ax=b via MATLAB factorization:\n') ; +fprintf ('x = U \\ (L \\ (P * b)) ; x (q) = x ;\n') ; +xm = U \ (L \ (P * b)) ; +xm (q) = xm ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (xu - xm, Inf)) ; + +fprintf ('\nMATLAB LU flop count: %d\n', luflop (L, U)) ; + +%------------------------------------------------------------------------------- +% solve A'x=b +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Solve A''x=b:\n') ; + +fprintf ('Solving A''x=b via UMFPACK:\n') ; +[xu, info] = umfpack (b', '/', A, control) ; +xu = xu' ; + +fprintf ('Solving A''x=b via MATLAB:\n') ; +xm = (b'/A)' ; +x = xm ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% factor A' and then solve Ax=b using the factors of A' +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Compute C = A'', and compute the LU factorization of C.\n') ; +fprintf ('Factorizing A'' can sometimes be better than factorizing A itself\n'); +fprintf ('(less work and memory usage). Solve C''x=b; the solution is the\n') ; +fprintf ('same as the solution to Ax=b for the original A.\n'); + +C = A' ; + +% factorize C (P,Q) = L*U +[L, U, P, Q, R, info] = umfpack (C, control) ; + +fprintf ('\nP * (R\\C) * Q - L*U should be zero:\n') ; +fprintf ('norm (P*(R\\C)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... + norm (P * (R\C) * Q - L*U, 1), lu_normest (P * (R\C) * Q, L, U)) ; + +fprintf ('\nSolution to Ax=b via UMFPACK, using the factors of C:\n') ; +fprintf ('x = R \\ (P'' * (L'' \\ (U'' \\ (Q'' * b)))) ;\n') ; +xu = R \ (P' * (L' \ (U' \ (Q' * b)))) ; +x = xu ; + +fprintf ('Solution to Ax=b via MATLAB:\n') ; +xm = A\b ; +x = xm ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% solve Ax=B +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve AX=B, where B is n-by-10, and sparse\n') ; +B = sprandn (n, 10, 0.05) ; +XU = umfpack_solve (A, '\', B, control) ; +XM = A\B ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (XU - XM, Inf)) ; + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve AX=B, where B is n-by-10, and sparse, using umfpack_btf\n') ; +XU = umfpack_btf (A, B, control) ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (XU - XM, Inf)) ; + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve A''X=B, where B is n-by-10, and sparse\n') ; +XU = umfpack_solve (B', '/', A, control) ; +XM = B'/A ; + +fprintf ('Difference between UMFPACK and MATLAB solution: %g\n', ... + norm (XU - XM, Inf)) ; + +%------------------------------------------------------------------------------- +% compute the determinant +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('det(A): %g UMFPACK determinant: %g\n', det (A), umfpack (A, 'det')) ; diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m.out b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_demo.m.out @@ -0,0 +1,76 @@ +>> umfpack_demo + +Enter the printing level for UMFPACK's output statistics: +0: none, 1: errors only, 2: statistics, 4: print some of outputs +5: print all output [default is 1]: + +-------------------------------------------------------------- +Factor and solve a small system, Ax=b, using default parameters +Solving Ax=b via UMFPACK: +Solving Ax=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 0 + +-------------------------------------------------------------- + +Factorizing [L, U, P, Q, R] = umfpack (A) + +P * (R\A) * Q - L*U should be zero: +norm (P*(R\A)*Q - L*U, 1) = 6.80012e-16 (exact) 6.80012e-16 (estimated) + +Solution to Ax=b via UMFPACK factorization: +x = Q * (U \ (L \ (P * (R \ b)))) + +UMFPACK flop count: 2354 + +Factorizing [L, U, P] = lu (A (:, q)) +If you are using a version of MATLAB prior to V6.0, then the +following statement (q = colamd (A)) may fail. Either download +colamd from http://www.cise.ufl.edu/research/sparse, upgrade to +MATLAB V6.0 or later, or replace the statement with +q = colmmd (A) ; + +Solution to Ax=b via MATLAB factorization: +x = U \ (L \ (P * b)) ; x (q) = x ; +Difference between UMFPACK and MATLAB solution: 7.10543e-15 + +MATLAB LU flop count: 3164 + +-------------------------------------------------------------- +Solve A'x=b: +Solving A'x=b via UMFPACK: +Solving A'x=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 2.66454e-15 + +-------------------------------------------------------------- +Compute C = A', and compute the LU factorization of C. +Factorizing A' can sometimes be better than factorizing A itself +(less work and memory usage). Solve C'x=b; the solution is the +same as the solution to Ax=b for the original A. + +P * (R\C) * Q - L*U should be zero: +norm (P*(R\C)*Q - L*U, 1) = 1.94289e-16 (exact) 5.55112e-17 (estimated) + +Solution to Ax=b via UMFPACK, using the factors of C: +x = R \ (P' * (L' \ (U' \ (Q' * b)))) ; +Solution to Ax=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 7.10543e-15 + +-------------------------------------------------------------- + +Solve AX=B, where B is n-by-10, and sparse +Difference between UMFPACK and MATLAB solution: 6.72949e-14 + +-------------------------------------------------------------- + +Solve AX=B, where B is n-by-10, and sparse, using umfpack_btf +Difference between UMFPACK and MATLAB solution: 8.51541e-14 + +-------------------------------------------------------------- + +Solve A'X=B, where B is n-by-10, and sparse +Difference between UMFPACK and MATLAB solution: 7.99291e-14 + +-------------------------------------------------------------- +det(A): -4.07453e-05 UMFPACK determinant: -4.07453e-05 +>> +>> diary off diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_details.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_details.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_details.m @@ -0,0 +1,164 @@ +function [out1, out2, out3, out4, out5] = umfpack (in1, in2, in3, in4, in5) +% UMFPACK v4.4: details on each usage. +% +% Factor or solve a sparse linear system, returning either the solution x to +% Ax=b or A'x'=b', the factorization LU=PAQ, or LU=P(R\A)Q. A must be sparse. +% For the solve, A must be square and b must be a dense n-by-1 vector. For LU +% factorization, A can be rectangular. In both cases, A and/or b can be real +% or complex. +% +% UMFPACK analyzes the matrix and selects one of three strategies to factorize +% the matrix. It first finds a set of k initial pivot entries of zero Markowitz +% cost. This forms the first k rows and columns of L and U. The remaining +% submatrix S is then analyzed, based on the symmetry of the nonzero pattern of +% the submatrix and the values on the diagaonal. The strategies include: +% +% (1) unsymmetric: use a COLAMD pre-ordering, a column elimination tree +% post-ordering, refine the column ordering during factorization, +% and make no effort at selecting pivots on the diagonal. +% (2) 2-by-2: like the symmetric strategy (see below), except that local +% row permutations are first made to attempt to place large entries +% on the diagonal. +% (3) symmetric: use an AMD pre-ordering on the matrix S+S', an +% elimination tree post-ordering, do not refine the column ordering +% during factorization, and attempt to select pivots on the diagonal. +% +% Each of the following uses of umfpack (except for "Control = umfpack") is +% stand-alone. That is, no call to umfpack is required for any subsequent +% call. In each usage, the Info output argument is optional. +% +% Usage: +% +% [x, Info] = umfpack (A, '\', b) ; +% [x, Info] = umfpack (A, '\', b, Control) ; +% [x, Info] = umfpack (A, Qinit, '\', b, Control) ; +% [x, Info] = umfpack (A, Qinit, '\', b) ; +% +% Solves Ax=b (similar to x = A\b in MATLAB). +% +% [x, Info] = umfpack (b, '/', A) ; +% [x, Info] = umfpack (b, '/', A, Control) ; +% [x, Info] = umfpack (b, '/', A, Qinit) ; +% [x, Info] = umfpack (b, '/', A, Qinit, Control) ; +% +% Solves A'x'=b' (similar to x = b/A in MATLAB). +% +% [L, U, P, Q, R, Info] = umfpack (A) ; +% [L, U, P, Q, R, Info] = umfpack (A, Control) ; +% [L, U, P, Q, R, Info] = umfpack (A, Qinit) ; +% [L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ; +% +% Returns the LU factorization of A. P and Q are returned as permutation +% matrices. R is a diagonal sparse matrix of scale factors for the rows +% of A, L is lower triangular, and U is upper triangular. The +% factorization is L*U = P*(R\A)*Q. You can turn off scaling by setting +% Control (17) to zero (in which case R = speye (m)), or by using the +% following syntaxes (in which case Control (17) is ignored): +% +% [L, U, P, Q] = umfpack (A) ; +% [L, U, P, Q] = umfpack (A, Control) ; +% [L, U, P, Q] = umfpack (A, Qinit) ; +% [L, U, P, Q] = umfpack (A, Qinit, Control) ; +% +% Same as above, except that no row scaling is performed. The Info array +% is not returned, either. +% +% [P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ; +% [P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic', Control) ; +% [P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic') ; +% [P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic', Control); +% +% Performs only the fill-reducing column pre-ordering (including the +% elimination tree post-ordering) and symbolic factorization. Q1 is the +% initial column permutation (either from colamd, amd, or the input +% ordering Qinit), possibly followed by a column elimination tree post- +% ordering or a symmetric elimination tree post-ordering, depending on +% the strategy used. +% +% For the unsymmetric strategy, P1 is the row ordering induced by Q1 +% (row-merge order). For the 2-by-2 strategy, P1 is the row ordering that +% places large entries on the diagonal of P1*A*Q1. For the symmetric +% strategy, P1 = Q1. +% +% Fr is a (nfr+1)-by-4 array containing information about each frontal +% matrix, where nfr <= n is the number of frontal matrices. Fr (:,1) is +% the number of pivot columns in each front, and Fr (:,2) is the parent +% of each front in the supercolumn elimination tree. Fr (k,2) is zero if +% k is a root. The first Fr (1,1) columns of P1*A*Q1 are the pivot +% columns for the first front, the next Fr (2,1) columns of P1*A*Q1 +% are the pivot columns for the second front, and so on. +% +% For the unsymmetric strategy, Fr (:,3) is the row index of the first +% row in P1*A*Q1 whose leftmost nonzero entry is in a pivot column for +% the kth front. Fr (:,4) is the leftmost descendent of the kth front. +% Rows in the range Fr (Fr (k,4),3) to Fr (k+1,3)-1 form the entire set +% of candidate pivot rows for the kth front (some of these will typically +% have been selected as pivot rows of fronts Fr (k,3) to k-1, before the +% factorization reaches the kth front. If front k is a leaf node, then +% Fr (k,4) is k. +% +% Ch is a (nchains+1)-by-3 array containing information about each "chain" +% (unifrontal sequence) of frontal matrices, and where nchains <= nfr +% is the number of chains. The ith chain consists of frontal matrices. +% Chain (i,1) to Chain (i+1,1)-1, and the largest front in chain i is +% Chain (i,2)-by-Chain (i,3). +% +% This use of umfpack is not required to factor or solve a linear system +% in MATLAB. It analyzes the matrix A and provides information only. +% The MATLAB statement "treeplot (Fr (:,2)')" plots the column elimination +% tree. +% +% Control = umfpack ; +% +% Returns a 20-by-1 vector of default parameter settings for umfpack. +% +% umfpack_report (Control, Info) ; +% +% Prints the current Control settings, and Info +% +% det = umfpack (A, 'det') ; +% [det dexp] = umfpack (A, 'det') ; +% +% Computes the determinant of A. The 2nd form returns the determinant +% in the form det*10^dexp, where det is in the range +/- 1 to 10, +% which helps to avoid overflow/underflow when dexp is out of range of +% normal floating-point numbers. +% +% If present, Qinit is a user-supplied 1-by-n permutation vector. It is an +% initial fill-reducing column pre-ordering for A; if not present, then colamd +% or amd are used instead. If present, Control is a user-supplied 20-by-1 +% array. Control and Info are optional; if Control is not present, defaults +% are used. If a Control entry is NaN, then the default is used for that entry. +% +% +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. +% +% UMFPACK License: +% +% Your use or distribution of UMFPACK or any modified version of +% UMFPACK implies that you agree to this License. +% +% THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +% EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +% +% Permission is hereby granted to use or copy this program, provided +% that the Copyright, this License, and the Availability of the original +% version is retained on all copies. User documentation of any code that +% uses UMFPACK or any modified version of UMFPACK code must cite the +% Copyright, this License, the Availability note, and "Used by permission." +% Permission to modify the code and to distribute modified code is granted, +% provided the Copyright, this License, and the Availability note are +% retained, and a notice that the code was modified is included. This +% software was developed with support from the National Science Foundation, +% and is provided to you free of charge. +% +% Availability: http://www.cise.ufl.edu/research/sparse/umfpack +% +% See also umfpack, umfpack_make, umfpack_report, +% umfpack_demo, and umfpack_simple. + +more on +help umfpack_details +more off + diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_make.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_make.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_make.m @@ -0,0 +1,356 @@ +function umfpack_make +% UMFPACK_MAKE +% +% Compiles the UMFPACK mexFunction and then runs a simple demo. +% +% See also: umfpack, umfpack_details, umfpack_report, umfpack_demo, and +% umfpack_simple. +% +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +help umfpack_make + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Now compiling the UMFPACK and AMD mexFunctions.\n') ; +fprintf ('--------------------------------------------------------------\n') ; + +try + % ispc does not appear in MATLAB 5.3 + pc = ispc ; +catch + % if ispc fails, assume we aren't on a Windows PC. + pc = 0 ; +end + +obj = 'o' ; +blas_lib = '' ; +if (pc) + obj = 'obj' ; +end + +%------------------------------------------------------------------------------- +% BLAS option +%------------------------------------------------------------------------------- + +msg = [ ... + '\nUsing the BLAS is faster, but might not compile correctly.\n', ... + 'If you get an error stating that dgemm, dgemv, dger, zgemm,\n', ... + 'zgemv, and/or zger are not defined, then recompile without the\n', ... + 'BLAS. You can ignore warnings that these routines are implicitly\n', ... + 'declared.\n\nPlease select one of the following options: \n', ... + ' 1: attempt to compile with the BLAS (default)\n', ... + ' 2: do not use the BLAS\n'] ; +fprintf (msg) ; +blas = input (': ') ; +if (isempty (blas)) + blas = 1 ; +end +if (blas == 1) + % try to link to MATLAB's built-in BLAS + blas = '' ; + if (pc) + % the default lcc compiler needs this library to access the BLAS + blas_lib = ' libmwlapack.lib' ; + msg = [ ... + '\nCheck to see if you have a file called libmwlapack.lib in the\n', ... + '\\extern\\lib\\win32\\lcc\\ directory, where is ', ... + 'the\ndirectory where MATLAB is installed. If a file of that ', ... + 'name is already\nthere, then you don''t have to do anything. ', ... + 'Otherwise, you must first\ncopy the libmwlapack.lib file from ', ... + 'the umfpack\\lcc_lib\\ directory to the\n', ... + '\\extern\\lib\\win32\\lcc\\ directory. Next, type\n\n', ... + ' mex -setup\n\n', ... + 'at the MATLAB prompt, and ask MATLAB to select the lcc compiler. ',... + 'You can skip\nall of this if you have already done it, or have ', ... + 'configured mex to use\na different compiler. If you are using ', ... + 'Norton anti-virus software on Windows\n98SE, then you need to ', ... + 'exit MATLAB, turn off virus checking, and restart MATLAB\n', ... + 'before you can use the mex command or compile UMFPACK.\n', ... + 'You may also need to turn off virus checking in other cases.\n', ... + '\nHit enter to continue, or type control-C if you do not wish to '] ; + fprintf (msg) ; + input ('proceed: ') ; + end + fprintf ('\nUsing the BLAS (recommended).\n') ; +else + % No BLAS + fprintf ('\nNot using the BLAS. UMFPACK will be slow.\n') ; + blas = ' -DNBLAS' ; +end + +%------------------------------------------------------------------------------- +% -DNUTIL option (using utMalloc or mxMalloc) +%------------------------------------------------------------------------------- + +utils = '' ; + +if (~pc) + msg = [ ... + '--------------------------------------------------------------\n', ... + '\nUMFPACK uses MATLAB''s memory allocation routines. The internal', ... + '\nutMalloc, utFree, and utRealloc allow for better use of memory,', ... + '\nbut they are internal utility routines that are not documented.\n', ... + 'Thus, they might not always work. Using mxMalloc, mxFree, and\n', ... + 'mxRealloc works, but UMFPACK might run out of memory when solving\n', ... + 'problems that it could otherwise solve. Try using the default.\n', ... + 'If you get an error stating that utMalloc, utFree, and/or\n', ... + 'utRealloc are not defined, then recompile with the mx* routines.\n', ... + '\nPlease select one of the following options:\n', ... + ' 1: attempt to use the ut* routines (default)\n', ... + ' 2: use the standard mx* routines\n'] ; + fprintf (msg) ; + utils = input (': ') ; + if (isempty (utils)) + utils = 1 ; + end + if (utils == 2) + fprintf ('\nNot using utMalloc, utFree, or utRealloc\n') ; + utils = ' -DNUTIL' ; + else + fprintf ('\nUsing utMalloc, utFree, and utRealloc\n') ; + utils = '' ; + end +end + +%------------------------------------------------------------------------------- +% -DNPOSIX option (for sysconf and times timer routines) +%------------------------------------------------------------------------------- + +posix = '' ; + +if (~pc) + msg = [ ... + '--------------------------------------------------------------\n', ... + '\nUMFPACK can use the POSIX routines sysconf () and times ()\n', ... + 'to provide CPU time and wallclock time statistics. If you do not\n', ... + 'have a POSIX-compliant operating system, then UMFPACK won''t\n', ... + 'compile. If you don''t know which option to pick, try the\n', ... + 'default. If you get an error saying that sysconf and/or times\n', ... + 'are not defined, then recompile with the non-POSIX option.\n', ... + '\nPlease select one of the following options:\n', ... + ' 1: use POSIX sysconf and times routines (default)\n', ... + ' 2: do not use POSIX routines\n'] ; + fprintf (msg) ; + posix = input (': ') ; + if (isempty (posix)) + posix = 1 ; + end + if (posix == 2) + fprintf ('\nNot using POSIX sysconf and times routines.\n') ; + posix = ' -DNPOSIX' ; + else + fprintf ('\nUsing POSIX sysconf and times routines.\n') ; + posix = '' ; + end +end + +%------------------------------------------------------------------------------- +% mex command +%------------------------------------------------------------------------------- + +umfdir = sprintf ('..%sSource%s', filesep, filesep) ; +amddir = sprintf ('..%s..%sAMD%sSource%s', filesep, filesep, filesep, filesep) ; +incdir = sprintf ( ... +' -I..%sInclude -I..%sSource -I..%s..%sAMD%sInclude -I..%s..%sAMD%sSource', ... +filesep,filesep, filesep, filesep, filesep, filesep, filesep, filesep) ; + +mx = sprintf ('mex -inline -O%s%s%s%s', blas, utils, posix, incdir) ; +msg = [ ... + '--------------------------------------------------------------\n', ... + '\nCompile options:\n%s\nNow compiling. Please wait.\n'] ; +fprintf (msg, mx) ; + +% The following is adapted from GNUmakefile + +%------------------------------------------------------------------------------- +% source files +%------------------------------------------------------------------------------- + +% non-user-callable umf_*.[ch] files: +umfch = { 'assemble', 'blas3_update', ... + 'build_tuples', 'create_element', ... + 'dump', 'extend_front', 'garbage_collection', ... + 'get_memory', 'init_front', 'kernel', ... + 'kernel_init', 'kernel_wrapup', ... + 'local_search', 'lsolve', 'ltsolve', ... + 'mem_alloc_element', 'mem_alloc_head_block', ... + 'mem_alloc_tail_block', 'mem_free_tail_block', ... + 'mem_init_memoryspace', ... + 'report_vector', 'row_search', 'scale_column', ... + 'set_stats', 'solve', 'symbolic_usage', 'transpose', ... + 'tuple_lengths', 'usolve', 'utsolve', 'valid_numeric', ... + 'valid_symbolic', 'grow_front', 'start_front', '2by2', ... + 'store_lu', 'scale' } ; + +% non-user-callable umf_*.[ch] files, int versions only (no real/complex): +umfint = { 'analyze', 'apply_order', 'colamd', 'free', 'fsize', ... + 'is_permutation', 'malloc', 'realloc', 'report_perm', ... + 'singletons' } ; + +% non-user-callable and user-callable amd_*.[ch] files (int versions only): +amd = { 'aat', '1', '2', 'dump', 'postorder', 'post_tree', 'defaults', ... + 'order', 'control', 'info', 'valid', 'preprocess' } ; + +% user-callable umfpack_*.[ch] files (real/complex): +user = { 'col_to_triplet', 'defaults', 'free_numeric', ... + 'free_symbolic', 'get_numeric', 'get_lunz', ... + 'get_symbolic', 'get_determinant', 'numeric', 'qsymbolic', ... + 'report_control', 'report_info', 'report_matrix', ... + 'report_numeric', 'report_perm', 'report_status', ... + 'report_symbolic', 'report_triplet', ... + 'report_vector', 'solve', 'symbolic', ... + 'transpose', 'triplet_to_col', 'scale' ... + 'load_numeric', 'save_numeric', 'load_symbolic', 'save_symbolic' } ; + +% user-callable umfpack_*.[ch], only one version +generic = { 'timer', 'tictoc' } ; + +M = cell (0) ; + +%------------------------------------------------------------------------------- +% Create the umfpack and amd mexFunctions for MATLAB (int versions only) +%------------------------------------------------------------------------------- + +for k = 1:length(umfint) + M = make (M, '%s -DDINT -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... + mx, umfint {k}, umfint {k}, 'm', obj, umfdir) ; +end + +rules = { [mx ' -DDINT'] , [mx ' -DZINT'] } ; +kinds = { 'md', 'mz' } ; + +for what = 1:2 + + rule = rules {what} ; + kind = kinds {what} ; + + M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s.%s', rule, 'ltsolve', 'lhsolve', kind, obj, umfdir) ; + + M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s.%s', rule, 'utsolve', 'uhsolve', kind, obj, umfdir) ; + + M = make (M, '%s -DDO_MAP -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_map_nox.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_nomap_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_nomap_nox.%s', rule, 'triplet', 'triplet', kind, obj, ... + umfdir) ; + + M = make (M, '%s -DDO_MAP -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_map_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -DFIXQ -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_fixq.%s', rule, 'assemble', 'assemble', kind, obj, umfdir) ; + + M = make (M, '%s -DDROP -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_drop.%s', rule, 'store_lu', 'store_lu', kind, obj, umfdir) ; + + for k = 1:length(umfch) + M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... + rule, umfch {k}, umfch {k}, kind, obj, umfdir) ; + end + + M = make (M, '%s -DWSOLVE -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_w%s.%s', rule, 'solve', 'solve', kind, obj, umfdir) ; + + for k = 1:length(user) + M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_%s.%s', rule, user {k}, user {k}, kind, obj, umfdir) ; + end +end + +for k = 1:length(generic) + M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_%s.%s', mx, generic {k}, generic {k}, 'm', obj, umfdir) ; +end + +%---------------------------------------- +% AMD routines (int only) +%---------------------------------------- + +for k = 1:length(amd) + M = make (M, '%s -DDINT -c %samd_%s.c', 'amd_%s.%s', 'amd_%s_%s.%s', ... + mx, amd {k}, amd {k}, 'm', obj, amddir) ; +end + +%---------------------------------------- +% compile the umfpack mexFunction +%---------------------------------------- + +C = sprintf ('%s -output umfpack umfpackmex.c', mx) ; +for i = 1:length (M) + C = [C ' ' (M {i})] ; +end +C = [C ' ' blas_lib] ; +cmd (C) ; + +%---------------------------------------- +% delete the object files +%---------------------------------------- + +for i = 1:length (M) + rmfile (M {i}) ; +end + +%---------------------------------------- +% compile the luflop mexFunction +%---------------------------------------- + +cmd (sprintf ('%s -output luflop luflopmex.c', mx)) ; + +fprintf ('\n\nCompilation has completed. Now trying the umfpack_simple demo.\n'); +umfpack_simple + +%------------------------------------------------------------------------------- +% rmfile: delete a file, but only if it exists +%------------------------------------------------------------------------------- + +function rmfile (file) +if (length (dir (file)) > 0) + delete (file) ; +end + +%------------------------------------------------------------------------------- +% cpfile: copy the src file to the filename dst, overwriting dst if it exists +%------------------------------------------------------------------------------- + +function cpfile (src, dst) +rmfile (dst) +if (length (dir (src)) == 0) + help umfpack_make + error (sprintf ('File does not exist: %s\n', src)) ; +end +copyfile (src, dst) ; + +%------------------------------------------------------------------------------- +% mvfile: move the src file to the filename dst, overwriting dst if it exists +%------------------------------------------------------------------------------- + +function mvfile (src, dst) +cpfile (src, dst) ; +rmfile (src) ; + +%------------------------------------------------------------------------------- +% cmd: display and execute a command +%------------------------------------------------------------------------------- + +function cmd (s) +fprintf ('.') ; +eval (s) ; + +%------------------------------------------------------------------------------- +% make: execute a "make" command for a source file +%------------------------------------------------------------------------------- + +function M = make (M, s, src, dst, rule, file1, file2, kind, obj, srcdir) +cmd (sprintf (s, rule, srcdir, file1)) ; +src = sprintf (src, file1, obj) ; +dst = sprintf (dst, kind, file2, obj) ; +mvfile (src, dst) ; +M {end + 1} = dst ; + diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_report.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_report.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_report.m @@ -0,0 +1,346 @@ +function umfpack_report (Control, Info) +% UMFPACK_REPORT +% +% umfpack_report (Control, Info) ; +% +% Prints the current Control settings for umfpack, and the statistical +% information returned by umfpack in the Info array. If Control is +% an empty matrix, then the default control settings are printed. +% +% Control is 20-by-1, and Info is 90-by-1. Not all entries are used. +% +% Alternative usages: +% +% umfpack_report ([ ], Info) ; print the default control parameters +% and the Info array. +% umfpack_report (Control) ; print the control parameters only. +% umfpack_report ; print the default control parameters +% and an empty Info array. +% +% See also umfpack, umfpack_make, umfpack_details, +% umfpack_demo, and umfpack_simple. + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +%------------------------------------------------------------------------------- +% get inputs, use defaults if input arguments not present +%------------------------------------------------------------------------------- + +% The contents of Control and Info are defined in umfpack.h +if (nargin < 1) + Control = [] ; +end +if (nargin < 2) + Info = [] ; +end +if (isempty (Control)) + Control = umfpack ; +end +if (isempty (Info)) + Info = [ 0 (-ones (1, 89)) ] ; +end + +%------------------------------------------------------------------------------- +% control settings +%------------------------------------------------------------------------------- + +fprintf ('\nUMFPACK Version 4.4: Control settings:\n\n') ; +fprintf (' Control (1): print level: %d\n', Control (1)) ; +fprintf (' Control (2): dense row parameter: %g\n', Control (2)) ; +fprintf (' "dense" rows have > max (16, (%g)*16*sqrt(n_col)) entries\n', Control (2)) ; +fprintf (' Control (3): dense column parameter: %g\n', Control (3)) ; +fprintf (' "dense" columns have > max (16, (%g)*16*sqrt(n_row)) entries\n', Control (3)) ; +fprintf (' Control (4): pivot tolerance: %g\n', Control (4)) ; +fprintf (' Control (5): max block size for dense matrix kernels: %d\n', Control (5)) ; +prstrat (' Control (6): strategy: %g ', Control (6)) ; +fprintf (' Control (7): initial allocation ratio: %g\n', Control (7)) ; +fprintf (' Control (8): max iterative refinement steps: %d\n', Control (8)) ; +fprintf (' Control (13): 2-by-2 pivot tolerance: %g\n', Control (13)) ; +fprintf (' Control (14): Q fixed during numeric factorization: %g ', Control (14)) ; +if (Control (14) > 0) + fprintf ('(yes)\n') ; +elseif (Control (14) < 0) + fprintf ('(no)\n') ; +else + fprintf ('(auto)\n') ; +end +fprintf (' Control (15): AMD dense row/column parameter: %g\n', Control (15)) ; +fprintf (' "dense" rows/columns in A+A'' have > max (16, (%g)*sqrt(n)) entries.\n', Control (15)) ; +fprintf (' Only used if the AMD ordering is used.\n') ; +fprintf (' Control (16): diagonal pivot tolerance: %g\n', Control (16)) ; +fprintf (' Only used if diagonal pivoting is attempted.\n') ; + +fprintf (' Control (17): scaling option: %g ', Control (17)) ; +if (Control (17) == 0) + fprintf ('(none)\n') ; +elseif (Control (17) == 2) + fprintf ('(scale the matrix by\n') ; + fprintf (' dividing each row by max. abs. value in each row)\n') ; +else + fprintf ('(scale the matrix by\n') ; + fprintf (' dividing each row by sum of abs. values in each row)\n') ; +end + +fprintf (' Control (18): frontal matrix allocation ratio: %g\n', Control (18)) ; +fprintf (' Control (19): drop tolerance: %g\n', Control (19)) ; +fprintf (' Control (20): AMD and COLAMD aggressive absorption: %g ', Control (20)) ; +yes_no (Control (20)) ; + +% compile-time options: + +fprintf ('\n The following options can only be changed at compile-time:\n') ; + +if (Control (9) == 1) + fprintf (' Control (9): compiled to use the BLAS\n') ; +else + fprintf (' Control (9): compiled without the BLAS\n') ; + fprintf (' (you will not get the best possible performance)\n') ; +end + +if (Control (10) == 1) + fprintf (' Control (10): compiled for MATLAB\n') ; +elseif (Control (10) == 2) + fprintf (' Control (10): compiled for MATLAB\n') ; + fprintf (' Uses internal utMalloc, utFree, utRealloc, utPrintf\n') ; + fprintf (' utDivideComplex, and utFdlibm_hypot routines.\n') ; +else + fprintf (' Control (10): not compiled for MATLAB\n') ; + fprintf (' Uses ANSI C malloc, free, realloc, and printf\n') ; + fprintf (' instead of mxMalloc, mxFree, mxRealloc, and mexPrintf.\n') ; + fprintf (' Printing will be in terms of 0-based matrix indexing,\n') ; + fprintf (' not 1-based as is expected in MATLAB. Diary output may\n') ; + fprintf (' not be properly recorded.\n') ; +end + +if (Control (11) == 2) + fprintf (' Control (11): uses POSIX times ( ) to get CPU time and wallclock time.\n') ; +elseif (Control (11) == 1) + fprintf (' Control (11): uses getrusage to get CPU time.\n') ; +else + fprintf (' Control (11): uses ANSI C clock to get CPU time.\n') ; + fprintf (' The CPU time may wrap around, type "help cputime".\n') ; +end + +if (Control (12) == 1) + fprintf (' Control (12): compiled with debugging enabled\n') ; + fprintf (' ###########################################\n') ; + fprintf (' ### This will be exceedingly slow! ########\n') ; + fprintf (' ###########################################\n') ; + if (Control (10) == 1) + fprintf (' Uses mxAssert.\n') ; + elseif (Control (10) == 2) + fprintf (' Uses utAssert.\n') ; + else + fprintf (' Uses ANSI C assert instead of mxAssert.\n') ; + end +else + fprintf (' Control (12): compiled for normal operation (no debugging)\n') ; +end + +%------------------------------------------------------------------------------- +% Info: +%------------------------------------------------------------------------------- + +if (nargin == 1) + return +end + +status = Info (1) ; +fprintf ('\nUMFPACK status: Info (1): %d, ', status) ; + +if (status == 0) + fprintf ('OK\n') ; +elseif (status == 1) + fprintf ('WARNING matrix is singular\n') ; +elseif (status == -1) + fprintf ('ERROR out of memory\n') ; +elseif (status == -3) + fprintf ('ERROR numeric LU factorization is invalid\n') ; +elseif (status == -4) + fprintf ('ERROR symbolic LU factorization is invalid\n') ; +elseif (status == -5) + fprintf ('ERROR required argument is missing\n') ; +elseif (status == -6) + fprintf ('ERROR n <= 0\n') ; +elseif (status <= -7 & status >= -12 | status == -14) + fprintf ('ERROR matrix A is corrupted\n') ; +elseif (status == -13) + fprintf ('ERROR invalid system\n') ; +elseif (status == -15) + fprintf ('ERROR invalid permutation\n') ; +elseif (status == -911) + fprintf ('ERROR internal error!\n') ; + fprintf ('Please report this error to Tim Davis (davis@cise.ufl.edu)\n') ; +else + fprintf ('ERROR unrecognized error. Info array corrupted\n') ; +end + +fprintf (' (a -1 means the entry has not been computed):\n') ; + +fprintf ('\n Basic statistics:\n') ; +fprintf (' Info (2): %d, # of rows of A\n', Info (2)) ; +fprintf (' Info (17): %d, # of columns of A\n', Info (17)) ; +fprintf (' Info (3): %d, nnz (A)\n', Info (3)) ; +fprintf (' Info (4): %d, Unit size, in bytes, for memory usage reported below\n', Info (4)) ; +fprintf (' Info (5): %d, size of int (in bytes)\n', Info (5)) ; +fprintf (' Info (6): %d, size of long (in bytes)\n', Info (6)) ; +fprintf (' Info (7): %d, size of pointer (in bytes)\n', Info (7)) ; +fprintf (' Info (8): %d, size of numerical entry (in bytes)\n', Info (8)) ; + +fprintf ('\n Pivots with zero Markowitz cost removed to obtain submatrix S:\n') ; +fprintf (' Info (57): %d, # of pivots with one entry in pivot column\n', Info (57)) ; +fprintf (' Info (58): %d, # of pivots with one entry in pivot row\n', Info (58)) ; +fprintf (' Info (59): %d, # of rows/columns in submatrix S (if square)\n', Info (59)) ; +fprintf (' Info (60): %d ') ; +if (Info (60) > 0) + fprintf ('submatrix S square and diagonal preserved\n') ; +elseif (Info (60) == 0) + fprintf ('submatrix S not square or diagonal not preserved\n') ; +else + fprintf ('\n') ; +end +fprintf (' Info (9): %d, # of "dense" rows in S\n', Info (9)) ; +fprintf (' Info (10): %d, # of empty rows in S\n', Info (10)) ; +fprintf (' Info (11): %d, # of "dense" columns in S\n', Info (11)) ; +fprintf (' Info (12): %d, # of empty columns in S\n', Info (12)) ; +fprintf (' Info (34): %g, symmetry of pattern of S\n', Info (34)) ; +fprintf (' Info (35): %d, # of off-diagonal nonzeros in S+S''\n', Info (35)) ; +fprintf (' Info (36): %d, nnz (diag (S))\n', Info (36)) ; + +fprintf ('\n 2-by-2 pivoting to place large entries on diagonal:\n') ; +fprintf (' Info (52): %d, # of small diagonal entries of S\n', Info (52)) ; +fprintf (' Info (53): %d, # of unmatched small diagonal entries\n', Info (53)) ; +fprintf (' Info (54): %g, symmetry of P2*S\n', Info (54)) ; +fprintf (' Info (55): %d, # of off-diagonal entries in (P2*S)+(P2*S)''\n', Info (55)) ; +fprintf (' Info (56): %d, nnz (diag (P2*S))\n', Info (56)) ; + +fprintf ('\n AMD results, for strict diagonal pivoting:\n') ; +fprintf (' Info (37): %d, est. nz in L and U\n', Info (37)) ; +fprintf (' Info (38): %g, est. flop count\n', Info (38)) ; +fprintf (' Info (39): %g, # of "dense" rows in S+S''\n', Info (39)) ; +fprintf (' Info (40): %g, est. max. nz in any column of L\n', Info (40)) ; + +fprintf ('\n Final strategy selection, based on the analysis above:\n') ; +prstrat (' Info (19): %d, strategy used ', Info (19)) ; +fprintf (' Info (20): %d, ordering used ', Info (20)) ; +if (Info (20) == 0) + fprintf ('(COLAMD on A)\n') ; +elseif (Info (20) == 1) + fprintf ('(AMD on A+A'')\n') ; +elseif (Info (20) == 2) + fprintf ('(provided by user)\n') ; +else + fprintf ('(undefined ordering option)\n') ; +end +fprintf (' Info (32): %d, Q fixed during numeric factorization: ', Info (32)) ; +yes_no (Info (32)) ; +fprintf (' Info (33): %d, prefer diagonal pivoting: ', Info (33)) ; +yes_no (Info (33)) ; + +fprintf ('\n symbolic analysis time and memory usage:\n') ; +fprintf (' Info (13): %d, defragmentations during symbolic analysis\n', Info (13)) ; +fprintf (' Info (14): %d, memory used during symbolic analysis (Units)\n', Info (14)) ; +fprintf (' Info (15): %d, final size of symbolic factors (Units)\n', Info (15)) ; +fprintf (' Info (16): %.2f, symbolic analysis CPU time (seconds)\n', Info (16)) ; +fprintf (' Info (18): %.2f, symbolic analysis wall clock time (seconds)\n', Info (18)) ; + +fprintf ('\n Estimates computed in the symbolic analysis:\n') ; +fprintf (' Info (21): %d, est. size of LU factors (Units)\n', Info (21)) ; +fprintf (' Info (22): %d, est. total peak memory usage (Units)\n', Info (22)) ; +fprintf (' Info (23): %d, est. factorization flop count\n', Info (23)) ; +fprintf (' Info (24): %d, est. nnz (L)\n', Info (24)) ; +fprintf (' Info (25): %d, est. nnz (U)\n', Info (25)) ; +fprintf (' Info (26): %d, est. initial size, variable-part of LU (Units)\n', Info (26)) ; +fprintf (' Info (27): %d, est. peak size, of variable-part of LU (Units)\n', Info (27)) ; +fprintf (' Info (28): %d, est. final size, of variable-part of LU (Units)\n', Info (28)) ; +fprintf (' Info (29): %d, est. max frontal matrix size (# of entries)\n', Info (29)) ; +fprintf (' Info (30): %d, est. max # of rows in frontal matrix\n', Info (30)) ; +fprintf (' Info (31): %d, est. max # of columns in frontal matrix\n', Info (31)) ; + +fprintf ('\n Computed in the numeric factorization (estimates shown above):\n') ; +fprintf (' Info (41): %d, size of LU factors (Units)\n', Info (41)) ; +fprintf (' Info (42): %d, total peak memory usage (Units)\n', Info (42)) ; +fprintf (' Info (43): %d, factorization flop count\n', Info (43)) ; +fprintf (' Info (44): %d, nnz (L)\n', Info (44)) ; +fprintf (' Info (45): %d, nnz (U)\n', Info (45)) ; +fprintf (' Info (46): %d, initial size of variable-part of LU (Units)\n', Info (46)) ; +fprintf (' Info (47): %d, peak size of variable-part of LU (Units)\n', Info (47)) ; +fprintf (' Info (48): %d, final size of variable-part of LU (Units)\n', Info (48)) ; +fprintf (' Info (49): %d, max frontal matrix size (# of numerical entries)\n', Info (49)) ; +fprintf (' Info (50): %d, max # of rows in frontal matrix\n', Info (50)) ; +fprintf (' Info (51): %d, max # of columns in frontal matrix\n', Info (51)) ; + +fprintf ('\n Computed in the numeric factorization (no estimates computed a priori):\n') ; +fprintf (' Info (61): %d, defragmentations during numeric factorization\n', Info (61)) ; +fprintf (' Info (62): %d, reallocations during numeric factorization\n', Info (62)) ; +fprintf (' Info (63): %d, costly reallocations during numeric factorization\n', Info (63)) ; +fprintf (' Info (64): %d, integer indices in compressed pattern of L and U\n', Info (64)) ; +fprintf (' Info (65): %d, numerical values stored in L and U\n', Info (65)) ; +fprintf (' Info (66): %.2f, numeric factorization CPU time (seconds)\n', Info (66)) ; +fprintf (' Info (76): %.2f, numeric factorization wall clock time (seconds)\n', Info (76)) ; +if (Info (66) > 0.05 & Info (43) > 0) +fprintf (' mflops in numeric factorization phase: %.2f\n', 1e-6 * Info (43) / Info (66)) ; +end +fprintf (' Info (67): %d, nnz (diag (U))\n', Info (67)) ; +fprintf (' Info (68): %g, reciprocal condition number estimate\n', Info (68)) ; +fprintf (' Info (69): %g, matrix was ', Info (69)) ; +if (Info (69) == 0) + fprintf ('not scaled\n') ; +elseif (Info (69) == 2) + fprintf ('scaled (row max)\n') ; +else + fprintf ('scaled (row sum)\n') ; +end +fprintf (' Info (70): %g, min. scale factor of rows of A\n', Info (70)) ; +fprintf (' Info (71): %g, max. scale factor of rows of A\n', Info (71)) ; +fprintf (' Info (72): %g, min. abs. on diagonal of U\n', Info (72)) ; +fprintf (' Info (73): %g, max. abs. on diagonal of U\n', Info (73)) ; +fprintf (' Info (74): %g, initial allocation parameter used\n', Info (74)) ; +fprintf (' Info (75): %g, # of forced updates due to frontal growth\n', Info (75)) ; +fprintf (' Info (77): %d, # of off-diaogonal pivots\n', Info (77)) ; +fprintf (' Info (78): %d, nnz (L), if no small entries dropped\n', Info (78)) ; +fprintf (' Info (79): %d, nnz (U), if no small entries dropped\n', Info (79)) ; +fprintf (' Info (80): %d, # of small entries dropped\n', Info (80)) ; + +fprintf ('\n Computed in the solve step:\n') ; +fprintf (' Info (81): %d, iterative refinement steps taken\n', Info (81)) ; +fprintf (' Info (82): %d, iterative refinement steps attempted\n', Info (82)) ; +fprintf (' Info (83): %g, omega(1), sparse-backward error estimate\n', Info (83)) ; +fprintf (' Info (84): %g, omega(2), sparse-backward error estimate\n', Info (84)) ; +fprintf (' Info (85): %d, solve flop count\n', Info (85)) ; +fprintf (' Info (86): %.2f, solve CPU time (seconds)\n', Info (86)) ; +fprintf (' Info (87): %.2f, solve wall clock time (seconds)\n', Info (87)) ; + +fprintf ('\n Info (88:90): unused\n\n') ; + +%------------------------------------------------------------------------------- + +function prstrat (fmt, strategy) +fprintf (fmt, strategy) ; +if (strategy == 1) + fprintf ('(unsymmetric)\n') ; + fprintf (' Q = COLAMD (A), Q refined during numerical\n') ; + fprintf (' factorization, and no attempt at diagonal pivoting.\n') ; +elseif (strategy == 2) + fprintf ('(symmetric, with 2-by-2 pivoting)\n') ; + fprintf (' P2 = row permutation to place large values on the diagonal\n') ; + fprintf (' Q = AMD (P2*A+(P2*A)''), Q not refined during numeric factorization,\n') ; + fprintf (' and diagonal pivoting attempted.\n') ; +elseif (strategy == 3) + fprintf ('(symmetric)\n') ; + fprintf (' Q = AMD (A+A''), Q not refined during numeric factorization,\n') ; + fprintf (' and diagonal pivoting (P=Q'') attempted.\n') ; +else + strategy = 0 ; + fprintf ('(auto)\n') ; +end + +%------------------------------------------------------------------------------- + +function yes_no (s) +if (s == 0) + fprintf ('(no)\n') ; +else + fprintf ('(yes)\n') ; +end diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m @@ -0,0 +1,61 @@ +% umfpack_simple: a simple demo of UMFPACK +% +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. +% +% UMFPACK License: +% +% Your use or distribution of UMFPACK or any modified version of +% UMFPACK implies that you agree to this License. +% +% THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +% EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +% +% Permission is hereby granted to use or copy this program, provided +% that the Copyright, this License, and the Availability of the original +% version is retained on all copies. User documentation of any code that +% uses UMFPACK or any modified version of UMFPACK code must cite the +% Copyright, this License, the Availability note, and "Used by permission." +% Permission to modify the code and to distribute modified code is granted, +% provided the Copyright, this License, and the Availability note are +% retained, and a notice that the code was modified is included. This +% software was developed with support from the National Science Foundation, +% and is provided to you free of charge. +% +% Availability: http://www.cise.ufl.edu/research/sparse/umfpack +% +% See also: umfpack, umfpack_details + +help umfpack_simple +i = input ('Hit enter to agree to the above License: ', 's') ; +if (~isempty (i)) + error ('terminating') ; +end + +format short + +A = [ + 2 3 0 0 0 + 3 0 4 0 6 + 0 -1 -3 2 0 + 0 0 1 0 0 + 0 4 2 0 1 +] + +A = sparse (A) ; + +b = [8 45 -3 3 19]' + +fprintf ('Solution to Ax=b via UMFPACK:\n') ; +fprintf ('x1 = umfpack (A, ''\\'', b)\n') ; + +x1 = umfpack (A, '\', b) + +fprintf ('Solution to Ax=b via MATLAB:\n') ; +fprintf ('x2 = A\\b\n') ; + +x2 = A\b + +fprintf ('norm (x1-x2) should be small: %g\n', norm (x1-x2)) ; + +fprintf ('Type ''umfpack_demo'' for a full demo of UMFPACK\n') ; diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m.out b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_simple.m.out @@ -0,0 +1,75 @@ +>> umfpack_simple + umfpack_simple: a simple demo of UMFPACK + + UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. + All Rights Reserved. Type umfpack_details for License. + + UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + + Availability: http://www.cise.ufl.edu/research/sparse/umfpack + + See also: umfpack, umfpack_details + + + +Hit enter to agree to the above License: + +A = + + 2 3 0 0 0 + 3 0 4 0 6 + 0 -1 -3 2 0 + 0 0 1 0 0 + 0 4 2 0 1 + + +b = + + 8 + 45 + -3 + 3 + 19 + +Solution to Ax=b via UMFPACK: +x1 = umfpack (A, '\', b) + +x1 = + + 1.0000 + 2.0000 + 3.0000 + 4.0000 + 5.0000 + +Solution to Ax=b via MATLAB: +x2 = A\b + +x2 = + + 1.0000 + 2.0000 + 3.0000 + 4.0000 + 5.0000 + +norm (x1-x2) should be small: 1.28037e-15 +Type 'umfpack_demo' for a full demo of UMFPACK +>> diary off diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_solve.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_solve.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_solve.m @@ -0,0 +1,96 @@ +function x = umfpack_solve (arg1, op, arg2, Control) +% UMFPACK_SOLVE +% +% x = umfpack_solve (A, '\', b, Control) +% x = umfpack_solve (b, '/', A, Control) +% +% Computes x = A\b, or b/A, where A is square. Uses UMFPACK if A is sparse. +% The Control argument is optional. +% +% See also umfpack, umfpack_make, umfpack_details, umfpack_report, +% and umfpack_simple. + +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +%------------------------------------------------------------------------------- +% check inputs and get default control parameters +%------------------------------------------------------------------------------- + +if (op == '\') + A = arg1 ; + b = arg2 ; +elseif (op == '/') + A = arg2 ; + b = arg1 ; +else + help umfack_solve + error ('umfpack_solve: unrecognized operator') ; +end + +[m n] = size (A) ; +if (m ~= n) + help umfpack_solve + error ('umfpack_solve: A must be square') ; +end + +[m1 n1] = size (b) ; +if ((op == '\' & n ~= m1) | (op == '/' & n1 ~= m)) + help umfpack_solve + error ('umfpack_solve: b has the wrong dimensions') ; +end + +if (nargin < 4) + Control = umfpack ; +end + +%------------------------------------------------------------------------------- +% solve the system +%------------------------------------------------------------------------------- + +if (op == '\') + + if (~issparse (A)) + + % A is not sparse, so just use MATLAB + x = A\b ; + + elseif (n1 == 1 & ~issparse (b)) + + % the UMFPACK '\' requires b to be a dense column vector + x = umfpack (A, '\', b, Control) ; + + else + + % factorize with UMFPACK and do the forward/back solves in MATLAB + [L, U, P, Q, R] = umfpack (A, Control) ; + x = Q * (U \ (L \ (P * (R \ b)))) ; + + end + +else + + if (~issparse (A)) + + % A is not sparse, so just use MATLAB + x = b/A ; + + elseif (m1 == 1 & ~issparse (b)) + + % the UMFPACK '\' requires b to be a dense column vector + x = umfpack (b, '/', A, Control) ; + + else + + % factorize with UMFPACK and do the forward/back solves in MATLAB + % this mimics the behavior of x = b/A, except for the row scaling + [L, U, P, Q, R] = umfpack (A.', Control) ; + x = (Q * (U \ (L \ (P * (R \ (b.')))))).' ; + + % an alternative method: + % [L, U, P, Q, r] = umfpack (A, Control) ; + % x = (R \ (P' * (L.' \ (U.' \ (Q' * b.'))))).' ; + + end + +end diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_test.m b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_test.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpack_test.m @@ -0,0 +1,152 @@ +% UMFPACK_TEST: test UMFPACK solve: b/A, A\b with iterative refinement +% Requires the UFsparse package for downloading matrices from the UF +% sparse matrix library. +% +% UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. +% All Rights Reserved. Type umfpack_details for License. + +index = UFget ; + +f = find (index.nrows == index.ncols) ; +[ignore, i] = sort (index.nrows (f)) ; +f = f (i) ; + +Control = umfpack ; +Control (1) = 0 ; + +warning ('off', 'all') ; +figure (1) +clf + + +for i = f + + fprintf ('\nmatrix: %s %s %d\n', index.Group{i}, index.Name{i}, index.nrows(i)) ; + + Prob = UFget (i) ; + A = Prob.A ; + n = size (A,1) ; + + b = rand (1,n) ; + c = b' ; + + try + + %----------------------------------------------------------------------- + % symbolic factorization + %----------------------------------------------------------------------- + + [P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ; + subplot (2,2,1) + spy (A) + title ('A') + + subplot (2,2,2) + treeplot (Fr (1:end-1,2)') ; + title ('supercolumn etree') + + %----------------------------------------------------------------------- + % P(R\A)Q = LU + %----------------------------------------------------------------------- + + [L,U,P,Q,R,Info] = umfpack (A) ; + err = lu_normest (P*(R\A)*Q, L, U) ; + fprintf ('norm est PR\\AQ-LU: %g relative: %g\n', ... + err, err / norm (A,1)) ; + + subplot (2,2,3) + spy (P*A*Q) + title ('PAQ') ; + + cs = Info (57) ; + rs = Info (58) ; + + subplot (2,2,4) + hold off + spy (L|U) + hold on + if (cs > 0) + plot ([0 cs n n 0] + .5, [0 cs cs 0 0]+.5, 'c') ; + end + if (rs > 0) + plot ([0 rs rs 0 0] + cs +.5, [cs cs+rs n n cs]+.5, 'r') ; + end + + title ('LU factors') + drawnow + + %----------------------------------------------------------------------- + % PAQ = LU + %----------------------------------------------------------------------- + + [L,U,P,Q] = umfpack (A) ; + err = lu_normest (P*A*Q, L, U) ; + fprintf ('norm est PAQ-LU: %g relative: %g\n', ... + err, err / norm (A,1)) ; + + %----------------------------------------------------------------------- + % solve + %----------------------------------------------------------------------- + + x1 = b/A ; + y1 = A\c ; + m1 = norm (b-x1*A) ; + m2 = norm (A*y1-c) ; + + % factor the transpose + Control (8) = 2 ; + [x, info] = umfpack (A', '\', c, Control) ; + lunz0 = info (44) + info (45) - info (67) ; + r = norm (A'*x-c) ; + + fprintf (':: %8.2e matlab: %8.2e %8.2e\n', r, m1, m2) ; + + % factor the original matrix and solve xA=b + for ir = 0:4 + Control (8) = ir ; + [x, info] = umfpack (b, '/', A, Control) ; + r = norm (b-x*A) ; + if (ir == 0) + lunz1 = info (44) + info (45) - info (67) ; + end + fprintf ('%d: %8.2e %d %d\n', ir, r, info (81), info (82)) ; + end + + % factor the original matrix and solve Ax=b + for ir = 0:4 + Control (8) = ir ; + [x, info] = umfpack (A, '\', c, Control) ; + r = norm (A*x-c) ; + fprintf ('%d: %8.2e %d %d\n', ir, r, info (81), info (82)) ; + end + + fprintf ('lunz trans %12d no trans: %12d trans/notrans: %10.4f\n', ... + lunz0, lunz1, lunz0 / lunz1) ; + + %----------------------------------------------------------------------- + % get the determinant + %----------------------------------------------------------------------- + + det1 = det (A) ; + det2 = umfpack (A, 'det') ; + [det3 dexp3] = umfpack (A, 'det') ; + err = abs (det1-det2) ; + err3 = abs (det1 - (det3 * 10^dexp3)) ; + denom = det1 ; + if (denom == 0) + denom = 1 ; + end + err = err / denom ; + err3 = err3 / denom ; + fprintf ('det: %24.16e + (%24.16e)i MATLAB\n', real(det1), imag(det1)) ; + fprintf ('det: %24.16e + (%24.16e)i umfpack\n',real(det2), imag(det2)) ; + fprintf ('det: (%24.16e + (%24.16e)i) * 10^(%g) umfpack\n', real(det3), imag(det3), dexp3) ; + fprintf ('diff %g %g\n', err, err3) ; + + catch + fprintf ('failed\n') ; + end + +% pause + +end diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/umfpackmex.c b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpackmex.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/MATLAB/umfpackmex.c @@ -0,0 +1,1364 @@ +/* ========================================================================== */ +/* === UMFPACK mexFunction ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + MATLAB interface for umfpack. + + Factor or solve a sparse linear system, returning either the solution + x to Ax=b or A'x'=b', or the factorization LU=P(R\A)Q or LU=PAQ. A must be + sparse, with nonzero dimensions, but it may be complex, singular, and/or + rectangular. b must be a dense n-by-1 vector (real or complex). + L is unit lower triangular, U is upper triangular, and R is diagonal. + P and Q are permutation matrices (permutations of an identity matrix). + + The matrix A is scaled, by default. Each row i is divided by r (i), where + r (i) is the sum of the absolute values of the entries in that row. The + scaled matrix has an infinity norm of 1. The scale factors r (i) are + returned in a diagonal sparse matrix. If the factorization is: + + [L, U, P, Q, R] = umfpack (A) ; + + then the factorization is + + L*U = P * (R \ A) * Q + + This is safer than returning a matrix R such that L*U = P*R*A*Q, because + it avoids the division by small entries. If r(i) is subnormal, multiplying + by 1/r(i) would result in an IEEE Infinity, but dividing by r(i) is safe. + + The factorization + + [L, U, P, Q] = umfpack (A) ; + + returns LU factors such that L*U = P*A*Q, with no scaling. + + See umfpack.m, umfpack_details.m, and umfpack.h for details. + + Note that this mexFunction accesses only the user-callable UMFPACK routines. + Thus, is also provides another example of how user C code can access + UMFPACK. + + If NO_TRANSPOSE_FORWARD_SLASH is not defined at compile time, then the + forward slash (/) operator acts almost like x = b/A in MATLAB 6.1. It is + solved by factorizing the array transpose, and then x = (A.'\b.').' is + solved. This is the default behavior (for historical reasons), since + factorizing A can behave perform much differently than factorizing its + transpose. + + If NO_TRANSPOSE_FORWARD_SLASH is defined at compile time, then the forward + slash operator does not act like x=b/A in MATLAB 6.1. It is solved by + factorizing A, and then solving via the transposed L and U matrices. + The solution is still x = (A.'\b.').', except that A is factorized instead + of A.'. + + Modified for v4.3.1, Jan 10, 2005: default has been changed to + NO_TRANSPOSE_FORWARD_SLASH, to test iterative refinement for b/A. + v4.4: added method for computing the determinant. +*/ +#define NO_TRANSPOSE_FORWARD_SLASH /* default has changed for v4.3.1 */ + +#include "umfpack.h" +#include "mex.h" +#include "matrix.h" +#include +#include +#include + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define STRING_MATCH(s1,s2) (strcmp ((s1), (s2)) == 0) +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* ========================================================================== */ +/* === error ================================================================ */ +/* ========================================================================== */ + +/* Return an error message */ + +static void error +( + char *s, + int A_is_complex, + int nargout, + mxArray *pargout [ ], + double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO], + int status, + int do_info +) +{ + int i ; + double *OutInfo ; + if (A_is_complex) + { + umfpack_zi_report_status (Control, status) ; + umfpack_zi_report_info (Control, Info) ; + } + else + { + umfpack_di_report_status (Control, status) ; + umfpack_di_report_info (Control, Info) ; + } + if (do_info > 0) + { + /* return Info */ + pargout [do_info] = mxCreateDoubleMatrix (1, UMFPACK_INFO, mxREAL) ; + OutInfo = mxGetPr (pargout [do_info]) ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + OutInfo [i] = Info [i] ; + } + } + mexErrMsgTxt (s) ; +} + + +/* ========================================================================== */ +/* === UMFPACK ============================================================== */ +/* ========================================================================== */ + +void mexFunction +( + int nargout, /* number of outputs */ + mxArray *pargout [ ], /* output arguments */ + int nargin, /* number of inputs */ + const mxArray *pargin [ ] /* input arguments */ +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL], dx, dz, dexp ; + double *Lx, *Lz, *Ux, *Uz, *Ax, *Az, *Bx, *Bz, *Xx, *Xz, *User_Control, + *p, *q, *OutInfo, *p1, *p2, *p3, *p4, *Ltx, *Ltz, *Rs, *Px, *Qx ; + void *Symbolic, *Numeric ; + int *Lp, *Li, *Up, *Ui, *Ap, *Ai, *P, *Q, do_solve, lnz, unz, nn, i, + transpose, size, do_info, do_numeric, *Front_npivcol, op, k, *Rp, *Ri, + *Front_parent, *Chain_start, *Chain_maxrows, *Chain_maxcols, nz, status, + nfronts, nchains, *Ltp, *Ltj, *Qinit, print_level, status2, no_scale, + *Front_1strow, *Front_leftmostdesc, n_row, n_col, n_inner, sys, + ignore1, ignore2, ignore3, A_is_complex, B_is_complex, X_is_complex, + *Pp, *Pi, *Qp, *Qi, do_recip, do_det ; + mxArray *Amatrix, *Bmatrix, *User_Control_matrix, *User_Qinit ; + char *operator, *operation ; + mxComplexity Atype, Xtype ; + char warning [200] ; + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + int *Cp, *Ci ; + double *Cx, *Cz ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get inputs A, b, and the operation to perform */ + /* ---------------------------------------------------------------------- */ + + User_Control_matrix = (mxArray *) NULL ; + User_Qinit = (mxArray *) NULL ; + + do_info = 0 ; + do_solve = FALSE ; + do_numeric = TRUE ; + transpose = FALSE ; + no_scale = FALSE ; + do_det = FALSE ; + + /* find the operator */ + op = 0 ; + for (i = 0 ; i < nargin ; i++) + { + if (mxIsChar (pargin [i])) + { + op = i ; + break ; + } + } + + if (op > 0) + { + operator = mxArrayToString (pargin [op]) ; + + if (STRING_MATCH (operator, "\\")) + { + + /* -------------------------------------------------------------- */ + /* matrix left divide, x = A\b */ + /* -------------------------------------------------------------- */ + + /* + [x, Info] = umfpack (A, '\', b) ; + [x, Info] = umfpack (A, '\', b, Control) ; + [x, Info] = umfpack (A, Qinit, '\', b, Control) ; + [x, Info] = umfpack (A, Qinit, '\', b) ; + */ + + operation = "x = A\\b" ; + do_solve = TRUE ; + Amatrix = (mxArray *) pargin [0] ; + Bmatrix = (mxArray *) pargin [op+1] ; + + if (nargout == 2) + { + do_info = 1 ; + } + if (op == 2) + { + User_Qinit = (mxArray *) pargin [1] ; + } + if ((op == 1 && nargin == 4) || (op == 2 && nargin == 5)) + { + User_Control_matrix = (mxArray *) pargin [nargin-1] ; + } + if (nargin < 3 || nargin > 5 || nargout > 2) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + } + else if (STRING_MATCH (operator, "/")) + { + + /* -------------------------------------------------------------- */ + /* matrix right divide, x = b/A */ + /* -------------------------------------------------------------- */ + + /* + [x, Info] = umfpack (b, '/', A) ; + [x, Info] = umfpack (b, '/', A, Control) ; + [x, Info] = umfpack (b, '/', A, Qinit) ; + [x, Info] = umfpack (b, '/', A, Qinit, Control) ; + */ + + operation = "x = b/A" ; + do_solve = TRUE ; + transpose = TRUE ; + Amatrix = (mxArray *) pargin [2] ; + Bmatrix = (mxArray *) pargin [0] ; + + if (nargout == 2) + { + do_info = 1 ; + } + if (nargin == 5) + { + User_Qinit = (mxArray *) pargin [3] ; + User_Control_matrix = (mxArray *) pargin [4] ; + } + else if (nargin == 4) + { + /* Control is k-by-1 where k > 1, Qinit is 1-by-n */ + if (mxGetM (pargin [3]) == 1) + { + User_Qinit = (mxArray *) pargin [3] ; + } + else + { + User_Control_matrix = (mxArray *) pargin [3] ; + } + } + else if (nargin < 3 || nargin > 5 || nargout > 2) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + } + else if (STRING_MATCH (operator, "symbolic")) + { + + /* -------------------------------------------------------------- */ + /* symbolic factorization only */ + /* -------------------------------------------------------------- */ + + /* + [P Q Fr Ch Info] = umfpack (A, 'symbolic') ; + [P Q Fr Ch Info] = umfpack (A, 'symbolic', Control) ; + [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic') ; + [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic', Control) ; + */ + + operation = "symbolic factorization" ; + do_numeric = FALSE ; + Amatrix = (mxArray *) pargin [0] ; + + if (nargout == 5) + { + do_info = 4 ; + } + if (op == 2) + { + User_Qinit = (mxArray *) pargin [1] ; + } + if ((op == 1 && nargin == 3) || (op == 2 && nargin == 4)) + { + User_Control_matrix = (mxArray *) pargin [nargin-1] ; + } + if (nargin < 2 || nargin > 4 || nargout > 5 || nargout < 4) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + } + else if (STRING_MATCH (operator, "det")) + { + + /* -------------------------------------------------------------- */ + /* compute the determinant */ + /* -------------------------------------------------------------- */ + + /* + * [det] = umfpack (A, 'det') ; + * [dmantissa dexp] = umfpack (A, 'det') ; + */ + + operation = "determinant" ; + do_det = TRUE ; + Amatrix = (mxArray *) pargin [0] ; + if (nargin > 2 || nargout > 2) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + } + else + { + mexErrMsgTxt ("operator must be '/', '\\', or 'symbolic'") ; + } + mxFree (operator) ; + + } + else if (nargin > 0) + { + + /* ------------------------------------------------------------------ */ + /* LU factorization */ + /* ------------------------------------------------------------------ */ + + /* + with scaling: + [L, U, P, Q, R, Info] = umfpack (A) ; + [L, U, P, Q, R, Info] = umfpack (A, Qinit) ; + + scaling determined by Control settings: + [L, U, P, Q, R, Info] = umfpack (A, Control) ; + [L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ; + + with no scaling: + [L, U, P, Q] = umfpack (A) ; + [L, U, P, Q] = umfpack (A, Control) ; + [L, U, P, Q] = umfpack (A, Qinit) ; + [L, U, P, Q] = umfpack (A, Qinit, Control) ; + */ + + operation = "numeric factorization" ; + Amatrix = (mxArray *) pargin [0] ; + + no_scale = nargout <= 4 ; + + if (nargout == 6) + { + do_info = 5 ; + } + if (nargin == 3) + { + User_Qinit = (mxArray *) pargin [1] ; + User_Control_matrix = (mxArray *) pargin [2] ; + } + else if (nargin == 2) + { + /* Control is k-by-1 where k > 1, Qinit is 1-by-n */ + if (mxGetM (pargin [1]) == 1) + { + User_Qinit = (mxArray *) pargin [1] ; + } + else + { + User_Control_matrix = (mxArray *) pargin [1] ; + } + } + else if (nargin > 3 || nargout > 6 || nargout < 4) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + } + else + { + + /* ------------------------------------------------------------------ */ + /* return default control settings */ + /* ------------------------------------------------------------------ */ + + /* + Control = umfpack ; + umfpack ; + */ + + if (nargout > 1) + { + mexErrMsgTxt ("wrong number of arguments") ; + } + + pargout [0] = mxCreateDoubleMatrix (UMFPACK_CONTROL, 1, mxREAL) ; + User_Control = mxGetPr (pargout [0]) ; + umfpack_di_defaults (User_Control) ; + + return ; + } + + /* ---------------------------------------------------------------------- */ + /* check inputs */ + /* ---------------------------------------------------------------------- */ + + if (mxGetNumberOfDimensions (Amatrix) != 2) + { + mexErrMsgTxt ("input matrix A must be 2-dimensional") ; + } + n_row = mxGetM (Amatrix) ; + n_col = mxGetN (Amatrix) ; + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + if (do_solve && n_row != n_col) + { + mexErrMsgTxt ("input matrix A must square for '\\' or '/'") ; + } + if (!mxIsSparse (Amatrix)) + { + mexErrMsgTxt ("input matrix A must be sparse") ; + } + if (n_row == 0 || n_col == 0) + { + mexErrMsgTxt ("input matrix A cannot have zero rows or zero columns") ; + } + + /* The real/complex status of A determines which version to use, */ + /* (umfpack_di_* or umfpack_zi_*). */ + A_is_complex = mxIsComplex (Amatrix) ; + Atype = A_is_complex ? mxCOMPLEX : mxREAL ; + Ap = mxGetJc (Amatrix) ; + Ai = mxGetIr (Amatrix) ; + Ax = mxGetPr (Amatrix) ; + Az = mxGetPi (Amatrix) ; + + if (do_solve) + { + + if (n_row != n_col) + { + mexErrMsgTxt ("A must be square for \\ or /") ; + } + if (transpose) + { + if (mxGetM (Bmatrix) != 1 || mxGetN (Bmatrix) != nn) + { + mexErrMsgTxt ("b has the wrong dimensions") ; + } + } + else + { + if (mxGetM (Bmatrix) != nn || mxGetN (Bmatrix) != 1) + { + mexErrMsgTxt ("b has the wrong dimensions") ; + } + } + if (mxGetNumberOfDimensions (Bmatrix) != 2) + { + mexErrMsgTxt ("input matrix b must be 2-dimensional") ; + } + if (mxIsSparse (Bmatrix)) + { + mexErrMsgTxt ("input matrix b cannot be sparse") ; + } + if (mxGetClassID (Bmatrix) != mxDOUBLE_CLASS) + { + mexErrMsgTxt ("input matrix b must double precision matrix") ; + } + + B_is_complex = mxIsComplex (Bmatrix) ; + Bx = mxGetPr (Bmatrix) ; + Bz = mxGetPi (Bmatrix) ; + + X_is_complex = A_is_complex || B_is_complex ; + Xtype = X_is_complex ? mxCOMPLEX : mxREAL ; + } + + /* ---------------------------------------------------------------------- */ + /* set the Control parameters */ + /* ---------------------------------------------------------------------- */ + + if (A_is_complex) + { + umfpack_zi_defaults (Control) ; + } + else + { + umfpack_di_defaults (Control) ; + } + if (User_Control_matrix) + { + if (mxGetClassID (User_Control_matrix) != mxDOUBLE_CLASS || + mxIsSparse (User_Control_matrix)) + { + mexErrMsgTxt ("Control must be a dense real matrix") ; + } + size = UMFPACK_CONTROL ; + size = MIN (size, mxGetNumberOfElements (User_Control_matrix)) ; + User_Control = mxGetPr (User_Control_matrix) ; + for (i = 0 ; i < size ; i++) + { + Control [i] = User_Control [i] ; + } + } + + if (no_scale) + { + /* turn off scaling for [L, U, P, Q] = umfpack (A) ; + * ignoring the input value of Control (24) for the usage + * [L, U, P, Q] = umfpack (A, Control) ; */ + Control [UMFPACK_SCALE] = UMFPACK_SCALE_NONE ; + } + + if (mxIsNaN (Control [UMFPACK_PRL])) + { + print_level = UMFPACK_DEFAULT_PRL ; + } + else + { + print_level = (int) Control [UMFPACK_PRL] ; + } + + Control [UMFPACK_PRL] = print_level ; + + /* ---------------------------------------------------------------------- */ + /* get Qinit, if present */ + /* ---------------------------------------------------------------------- */ + + if (User_Qinit) + { + if (mxGetM (User_Qinit) != 1 || mxGetN (User_Qinit) != n_col) + { + mexErrMsgTxt ("Qinit must be 1-by-n_col") ; + } + if (mxGetNumberOfDimensions (User_Qinit) != 2) + { + mexErrMsgTxt ("input Qinit must be 2-dimensional") ; + } + if (mxIsComplex (User_Qinit)) + { + mexErrMsgTxt ("input Qinit must not be complex") ; + } + if (mxGetClassID (User_Qinit) != mxDOUBLE_CLASS) + { + mexErrMsgTxt ("input Qinit must be a double matrix") ; + } + if (mxIsSparse (User_Qinit)) + { + mexErrMsgTxt ("input Qinit must be dense") ; + } + Qinit = (int *) mxMalloc (n_col * sizeof (int)) ; + p = mxGetPr (User_Qinit) ; + for (k = 0 ; k < n_col ; k++) + { + /* convert from 1-based to 0-based indexing */ + Qinit [k] = ((int) (p [k])) - 1 ; + } + + } + else + { + /* umfpack_*_qsymbolic will call colamd to get Qinit. This is the */ + /* same as calling umfpack_*_symbolic with Qinit set to NULL*/ + Qinit = (int *) NULL ; + } + + /* ---------------------------------------------------------------------- */ + /* report the inputs A and Qinit */ + /* ---------------------------------------------------------------------- */ + + if (print_level >= 2) + { + /* print the operation */ + mexPrintf ("\numfpack: %s\n", operation) ; + } + + if (A_is_complex) + { + umfpack_zi_report_control (Control) ; + if (print_level >= 3) mexPrintf ("\nA: ") ; + (void) umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, + 1, Control) ; + if (Qinit) + { + if (print_level >= 3) mexPrintf ("\nQinit: ") ; + (void) umfpack_zi_report_perm (n_col, Qinit, Control) ; + } + } + else + { + umfpack_di_report_control (Control) ; + if (print_level >= 3) mexPrintf ("\nA: ") ; + (void) umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, + 1, Control) ; + if (Qinit) + { + if (print_level >= 3) mexPrintf ("\nQinit: ") ; + (void) umfpack_di_report_perm (n_col, Qinit, Control) ; + } + } + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + /* ---------------------------------------------------------------------- */ + /* create the array transpose for x = b/A */ + /* ---------------------------------------------------------------------- */ + + if (transpose) + { + /* note that in this case A will be square (nn = n_row = n_col) */ + /* x = (A.'\b.').' will be computed */ + + /* make sure Ci and Cx exist, avoid malloc of zero-sized arrays. */ + nz = MAX (Ap [nn], 1) ; + + Cp = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Ci = (int *) mxMalloc (nz * sizeof (int)) ; + Cx = (double *) mxMalloc (nz * sizeof (double)) ; + if (A_is_complex) + { + Cz = (double *) mxMalloc (nz * sizeof (double)) ; + status = umfpack_zi_transpose (nn, nn, Ap, Ai, Ax, Az, + (int *) NULL, (int *) NULL, Cp, Ci, Cx, Cz, FALSE) ; + } + else + { + status = umfpack_di_transpose (nn, nn, Ap, Ai, Ax, + (int *) NULL, (int *) NULL, Cp, Ci, Cx) ; + } + + if (status != UMFPACK_OK) + { + error ("transpose of A failed", A_is_complex, nargout, pargout, + Control, Info, status, do_info); + return ; + } + + /* modify pointers so that C will be factorized and solved, not A */ + Ap = Cp ; + Ai = Ci ; + Ax = Cx ; + if (A_is_complex) + { + Az = Cz ; + } + } +#endif + + /* ---------------------------------------------------------------------- */ + /* perform the symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + if (A_is_complex) + { + status = umfpack_zi_qsymbolic (n_row, n_col, Ap, Ai, Ax, Az, + Qinit, &Symbolic, Control, Info) ; + } + else + { + status = umfpack_di_qsymbolic (n_row, n_col, Ap, Ai, Ax, + Qinit, &Symbolic, Control, Info) ; + } + + if (Qinit) + { + mxFree (Qinit) ; + } + + if (status < 0) + { + error ("symbolic factorization failed", A_is_complex, nargout, pargout, + Control, Info, status, do_info) ; + return ; + } + + /* ---------------------------------------------------------------------- */ + /* report the Symbolic object */ + /* ---------------------------------------------------------------------- */ + + if (A_is_complex) + { + (void) umfpack_zi_report_symbolic (Symbolic, Control) ; + } + else + { + (void) umfpack_di_report_symbolic (Symbolic, Control) ; + } + + /* ---------------------------------------------------------------------- */ + /* perform numeric factorization, or just return symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + if (do_numeric) + { + + /* ------------------------------------------------------------------ */ + /* perform the numeric factorization */ + /* ------------------------------------------------------------------ */ + + if (A_is_complex) + { + status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric, + Control, Info) ; + } + else + { + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control, Info) ; + } + + /* ------------------------------------------------------------------ */ + /* free the symbolic factorization */ + /* ------------------------------------------------------------------ */ + + if (A_is_complex) + { + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_free_symbolic (&Symbolic) ; + } + + /* ------------------------------------------------------------------ */ + /* report the Numeric object */ + /* ------------------------------------------------------------------ */ + + if (status < 0) + { + error ("numeric factorization failed", A_is_complex, nargout, + pargout, Control, Info, status, do_info); + return ; + } + + if (A_is_complex) + { + (void) umfpack_zi_report_numeric (Numeric, Control) ; + } + else + { + (void) umfpack_di_report_numeric (Numeric, Control) ; + } + + /* ------------------------------------------------------------------ */ + /* return the solution, determinant, or the factorization */ + /* ------------------------------------------------------------------ */ + + if (do_solve) + { + /* -------------------------------------------------------------- */ + /* solve Ax=b or A'x'=b', and return just the solution x */ + /* -------------------------------------------------------------- */ + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + if (transpose) + { + /* A.'x.'=b.' gives the same x=b/A as solving A'x'=b' */ + /* since C=A.' was factorized, solve with sys = UMFPACK_A */ + /* since x and b are vectors, x.' and b.' are implicit */ + pargout [0] = mxCreateDoubleMatrix (1, nn, Xtype) ; + } + else + { + pargout [0] = mxCreateDoubleMatrix (nn, 1, Xtype) ; + } + sys = UMFPACK_A ; +#else + if (transpose) + { + /* If A is real, A'x=b is the same as A.'x=b. */ + /* x and b are vectors, so x and b are the same as x' and b'. */ + /* If A is complex, then A.'x.'=b.' gives the same solution x */ + /* as the complex conjugate transpose. If we used the A'x=b */ + /* option in umfpack_*_solve, we would have to form b' on */ + /* input and x' on output (negating the imaginary part). */ + /* We can save this work by just using the A.'x=b option in */ + /* umfpack_*_solve. Then, forming x.' and b.' is implicit, */ + /* since x and b are just vectors anyway. */ + /* In both cases, the system to solve is A.'x=b */ + pargout [0] = mxCreateDoubleMatrix (1, nn, Xtype) ; + sys = UMFPACK_Aat ; + } + else + { + pargout [0] = mxCreateDoubleMatrix (nn, 1, Xtype) ; + sys = UMFPACK_A ; + } +#endif + + /* -------------------------------------------------------------- */ + /* print the right-hand-side, B */ + /* -------------------------------------------------------------- */ + + if (print_level >= 3) mexPrintf ("\nright-hand side, b: ") ; + if (B_is_complex) + { + (void) umfpack_zi_report_vector (nn, Bx, Bz, Control) ; + } + else + { + (void) umfpack_di_report_vector (nn, Bx, Control) ; + } + + /* -------------------------------------------------------------- */ + /* solve the system */ + /* -------------------------------------------------------------- */ + + Xx = mxGetPr (pargout [0]) ; + Xz = mxGetPi (pargout [0]) ; + status2 = UMFPACK_OK ; + + if (A_is_complex) + { + if (!B_is_complex) + { + /* umfpack_zi_solve expects a complex B */ + Bz = (double *) mxCalloc (nn, sizeof (double)) ; + } + status = umfpack_zi_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, + Numeric, Control, Info) ; + if (!B_is_complex) + { + mxFree (Bz) ; + } + } + else + { + if (B_is_complex) + { + /* Ax=b when b is complex and A is sparse can be split */ + /* into two systems, A*xr=br and A*xi=bi, where r denotes */ + /* the real part and i the imaginary part of x and b. */ + status2 = umfpack_di_solve (sys, Ap, Ai, Ax, Xz, Bz, + Numeric, Control, Info) ; + } + status = umfpack_di_solve (sys, Ap, Ai, Ax, Xx, Bx, + Numeric, Control, Info) ; + } + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + /* -------------------------------------------------------------- */ + /* free the transposed matrix C */ + /* -------------------------------------------------------------- */ + + if (transpose) + { + mxFree (Cp) ; + mxFree (Ci) ; + mxFree (Cx) ; + if (A_is_complex) + { + mxFree (Cz) ; + } + } +#endif + + /* -------------------------------------------------------------- */ + /* free the Numeric object */ + /* -------------------------------------------------------------- */ + + if (A_is_complex) + { + umfpack_zi_free_numeric (&Numeric) ; + } + else + { + umfpack_di_free_numeric (&Numeric) ; + } + + /* -------------------------------------------------------------- */ + /* check error status */ + /* -------------------------------------------------------------- */ + + if (status < 0 || status2 < 0) + { + mxDestroyArray (pargout [0]) ; + error ("solve failed", A_is_complex, nargout, pargout, Control, + Info, status, do_info) ; + return ; + } + + /* -------------------------------------------------------------- */ + /* print the solution, X */ + /* -------------------------------------------------------------- */ + + if (print_level >= 3) mexPrintf ("\nsolution, x: ") ; + if (X_is_complex) + { + (void) umfpack_zi_report_vector (nn, Xx, Xz, Control) ; + } + else + { + (void) umfpack_di_report_vector (nn, Xx, Control) ; + } + + /* -------------------------------------------------------------- */ + /* warn about singular or near-singular matrices */ + /* -------------------------------------------------------------- */ + + /* no warning is given if Control (1) is zero */ + + if (Control [UMFPACK_PRL] >= 1) + { + if (status == UMFPACK_WARNING_singular_matrix) + { + sprintf (warning, "matrix is singular\n" + "Try increasing Control (%d) and Control (%d).\n" + "(Suppress this warning with Control (%d) = 0.)\n", + 1+UMFPACK_PIVOT_TOLERANCE, + 1+UMFPACK_SYM_PIVOT_TOLERANCE, + 1+UMFPACK_PRL) ; + mexWarnMsgTxt (warning) ; + } + else if (Info [UMFPACK_RCOND] < DBL_EPSILON) + { + sprintf (warning, "matrix is nearly singular, rcond = %g\n" + "Try increasing Control (%d) and Control (%d).\n" + "(Suppress this warning with Control (%d) = 0.)\n", + Info [UMFPACK_RCOND], + 1+UMFPACK_PIVOT_TOLERANCE, + 1+UMFPACK_SYM_PIVOT_TOLERANCE, + 1+UMFPACK_PRL) ; + mexWarnMsgTxt (warning) ; + } + } + + } + else if (do_det) + { + + /* -------------------------------------------------------------- */ + /* get the determinant */ + /* -------------------------------------------------------------- */ + + if (nargout == 2) + { + /* [det dexp] = umfpack (A, 'det') ; + * return determinant in the form det * 10^dexp */ + p = &dexp ; + } + else + { + /* [det] = umfpack (A, 'det') ; + * return determinant as a single scalar (overflow or + * underflow is much more likely) */ + p = (double *) NULL ; + } + if (A_is_complex) + { + status = umfpack_zi_get_determinant (&dx, &dz, p, + Numeric, Info) ; + umfpack_zi_free_numeric (&Numeric) ; + } + else + { + status = umfpack_di_get_determinant (&dx, p, + Numeric, Info) ; + umfpack_di_free_numeric (&Numeric) ; + dz = 0 ; + } + if (status < 0) + { + error ("extracting LU factors failed", A_is_complex, nargout, + pargout, Control, Info, status, do_info) ; + } + if (A_is_complex) + { + pargout [0] = mxCreateDoubleMatrix (1, 1, mxCOMPLEX) ; + p = mxGetPr (pargout [0]) ; + *p = dx ; + p = mxGetPi (pargout [0]) ; + *p = dz ; + } + else + { + pargout [0] = mxCreateDoubleMatrix (1, 1, mxREAL) ; + p = mxGetPr (pargout [0]) ; + *p = dx ; + } + if (nargout == 2) + { + pargout [1] = mxCreateDoubleMatrix (1, 1, mxREAL) ; + p = mxGetPr (pargout [1]) ; + *p = dexp ; + } + + } + else + { + + /* -------------------------------------------------------------- */ + /* get L, U, P, Q, and r */ + /* -------------------------------------------------------------- */ + + if (A_is_complex) + { + status = umfpack_zi_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + } + else + { + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + } + + if (status < 0) + { + if (A_is_complex) + { + umfpack_zi_free_numeric (&Numeric) ; + } + else + { + umfpack_di_free_numeric (&Numeric) ; + } + error ("extracting LU factors failed", A_is_complex, nargout, + pargout, Control, Info, status, do_info) ; + return ; + } + + /* avoid malloc of zero-sized arrays */ + lnz = MAX (lnz, 1) ; + unz = MAX (unz, 1) ; + + /* get temporary space, for the *** ROW *** form of L */ + Ltp = (int *) mxMalloc ((n_row+1) * sizeof (int)) ; + Ltj = (int *) mxMalloc (lnz * sizeof (int)) ; + Ltx = (double *) mxMalloc (lnz * sizeof (double)) ; + if (A_is_complex) + { + Ltz = (double *) mxMalloc (lnz * sizeof (double)) ; + } + else + { + Ltz = (double *) NULL ; + } + + /* create permanent copy of the output matrix U */ + pargout [1] = mxCreateSparse (n_inner, n_col, unz, Atype) ; + Up = mxGetJc (pargout [1]) ; + Ui = mxGetIr (pargout [1]) ; + Ux = mxGetPr (pargout [1]) ; + Uz = mxGetPi (pargout [1]) ; + + /* temporary space for the integer permutation vectors */ + P = (int *) mxMalloc (n_row * sizeof (int)) ; + Q = (int *) mxMalloc (n_col * sizeof (int)) ; + + /* get scale factors, if requested */ + status2 = UMFPACK_OK ; + if (!no_scale) + { + /* create a diagonal sparse matrix for the scale factors */ + pargout [4] = mxCreateSparse (n_row, n_row, n_row, mxREAL) ; + Rp = mxGetJc (pargout [4]) ; + Ri = mxGetIr (pargout [4]) ; + for (i = 0 ; i < n_row ; i++) + { + Rp [i] = i ; + Ri [i] = i ; + } + Rp [n_row] = n_row ; + Rs = mxGetPr (pargout [4]) ; + } + else + { + Rs = (double *) NULL ; + } + + /* get Lt, U, P, Q, and Rs from the numeric object */ + if (A_is_complex) + { + status = umfpack_zi_get_numeric (Ltp, Ltj, Ltx, Ltz, Up, Ui, Ux, + Uz, P, Q, (double *) NULL, (double *) NULL, + &do_recip, Rs, Numeric) ; + umfpack_zi_free_numeric (&Numeric) ; + } + else + { + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Ui, + Ux, P, Q, (double *) NULL, + &do_recip, Rs, Numeric) ; + umfpack_di_free_numeric (&Numeric) ; + } + + /* for the mexFunction, -DNRECIPROCAL must be set, + * so do_recip must be FALSE */ + + if (status < 0 || status2 < 0 || do_recip) + { + mxFree (Ltp) ; + mxFree (Ltj) ; + mxFree (Ltx) ; + if (Ltz) mxFree (Ltz) ; + mxFree (P) ; + mxFree (Q) ; + mxDestroyArray (pargout [1]) ; + error ("extracting LU factors failed", A_is_complex, nargout, + pargout, Control, Info, status, do_info) ; + return ; + } + + /* create sparse permutation matrix for P */ + pargout [2] = mxCreateSparse (n_row, n_row, n_row, mxREAL) ; + Pp = mxGetJc (pargout [2]) ; + Pi = mxGetIr (pargout [2]) ; + Px = mxGetPr (pargout [2]) ; + for (k = 0 ; k < n_row ; k++) + { + Pp [k] = k ; + Px [k] = 1 ; + Pi [P [k]] = k ; + } + Pp [n_row] = n_row ; + + /* create sparse permutation matrix for Q */ + pargout [3] = mxCreateSparse (n_col, n_col, n_col, mxREAL) ; + Qp = mxGetJc (pargout [3]) ; + Qi = mxGetIr (pargout [3]) ; + Qx = mxGetPr (pargout [3]) ; + for (k = 0 ; k < n_col ; k++) + { + Qp [k] = k ; + Qx [k] = 1 ; + Qi [k] = Q [k] ; + } + Qp [n_col] = n_col ; + + /* permanent copy of L */ + pargout [0] = mxCreateSparse (n_row, n_inner, lnz, Atype) ; + Lp = mxGetJc (pargout [0]) ; + Li = mxGetIr (pargout [0]) ; + Lx = mxGetPr (pargout [0]) ; + Lz = mxGetPi (pargout [0]) ; + + /* convert L from row form to column form */ + if (A_is_complex) + { + /* non-conjugate array transpose */ + status = umfpack_zi_transpose (n_inner, n_row, Ltp, Ltj, Ltx, + Ltz, (int *) NULL, (int *) NULL, Lp, Li, Lx, Lz, FALSE) ; + } + else + { + status = umfpack_di_transpose (n_inner, n_row, Ltp, Ltj, Ltx, + (int *) NULL, (int *) NULL, Lp, Li, Lx) ; + } + + mxFree (Ltp) ; + mxFree (Ltj) ; + mxFree (Ltx) ; + if (Ltz) mxFree (Ltz) ; + + if (status < 0) + { + mxFree (P) ; + mxFree (Q) ; + mxDestroyArray (pargout [0]) ; + mxDestroyArray (pargout [1]) ; + mxDestroyArray (pargout [2]) ; + mxDestroyArray (pargout [3]) ; + error ("constructing L failed", A_is_complex, nargout, pargout, + Control, Info, status, do_info) ; + return ; + } + + /* -------------------------------------------------------------- */ + /* print L, U, P, and Q */ + /* -------------------------------------------------------------- */ + + if (A_is_complex) + { + if (print_level >= 3) mexPrintf ("\nL: ") ; + (void) umfpack_zi_report_matrix (n_row, n_inner, Lp, Li, + Lx, Lz, 1, Control) ; + if (print_level >= 3) mexPrintf ("\nU: ") ; + (void) umfpack_zi_report_matrix (n_inner, n_col, Up, Ui, + Ux, Uz, 1, Control) ; + if (print_level >= 3) mexPrintf ("\nP: ") ; + (void) umfpack_zi_report_perm (n_row, P, Control) ; + if (print_level >= 3) mexPrintf ("\nQ: ") ; + (void) umfpack_zi_report_perm (n_col, Q, Control) ; + } + else + { + if (print_level >= 3) mexPrintf ("\nL: ") ; + (void) umfpack_di_report_matrix (n_row, n_inner, Lp, Li, + Lx, 1, Control) ; + if (print_level >= 3) mexPrintf ("\nU: ") ; + (void) umfpack_di_report_matrix (n_inner, n_col, Up, Ui, + Ux, 1, Control) ; + if (print_level >= 3) mexPrintf ("\nP: ") ; + (void) umfpack_di_report_perm (n_row, P, Control) ; + if (print_level >= 3) mexPrintf ("\nQ: ") ; + (void) umfpack_di_report_perm (n_col, Q, Control) ; + } + + mxFree (P) ; + mxFree (Q) ; + + } + + } + else + { + + /* ------------------------------------------------------------------ */ + /* return the symbolic factorization */ + /* ------------------------------------------------------------------ */ + + Q = (int *) mxMalloc (n_col * sizeof (int)) ; + P = (int *) mxMalloc (n_row * sizeof (int)) ; + Front_npivcol = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Front_parent = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Front_1strow = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Front_leftmostdesc = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Chain_start = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Chain_maxrows = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + Chain_maxcols = (int *) mxMalloc ((nn+1) * sizeof (int)) ; + + if (A_is_complex) + { + status = umfpack_zi_get_symbolic (&ignore1, &ignore2, &ignore3, + &nz, &nfronts, &nchains, P, Q, Front_npivcol, + Front_parent, Front_1strow, Front_leftmostdesc, + Chain_start, Chain_maxrows, Chain_maxcols, Symbolic) ; + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + status = umfpack_di_get_symbolic (&ignore1, &ignore2, &ignore3, + &nz, &nfronts, &nchains, P, Q, Front_npivcol, + Front_parent, Front_1strow, Front_leftmostdesc, + Chain_start, Chain_maxrows, Chain_maxcols, Symbolic) ; + umfpack_di_free_symbolic (&Symbolic) ; + } + + if (status < 0) + { + mxFree (P) ; + mxFree (Q) ; + mxFree (Front_npivcol) ; + mxFree (Front_parent) ; + mxFree (Front_1strow) ; + mxFree (Front_leftmostdesc) ; + mxFree (Chain_start) ; + mxFree (Chain_maxrows) ; + mxFree (Chain_maxcols) ; + error ("extracting symbolic factors failed", A_is_complex, nargout, + pargout, Control, Info, status, do_info) ; + return ; + } + + /* create sparse permutation matrix for P */ + pargout [0] = mxCreateSparse (n_row, n_row, n_row, mxREAL) ; + Pp = mxGetJc (pargout [0]) ; + Pi = mxGetIr (pargout [0]) ; + Px = mxGetPr (pargout [0]) ; + for (k = 0 ; k < n_row ; k++) + { + Pp [k] = k ; + Px [k] = 1 ; + Pi [P [k]] = k ; + } + Pp [n_row] = n_row ; + + /* create sparse permutation matrix for Q */ + pargout [1] = mxCreateSparse (n_col, n_col, n_col, mxREAL) ; + Qp = mxGetJc (pargout [1]) ; + Qi = mxGetIr (pargout [1]) ; + Qx = mxGetPr (pargout [1]) ; + for (k = 0 ; k < n_col ; k++) + { + Qp [k] = k ; + Qx [k] = 1 ; + Qi [k] = Q [k] ; + } + Qp [n_col] = n_col ; + + /* create Fr */ + pargout [2] = mxCreateDoubleMatrix (nfronts+1, 4, mxREAL) ; + + p1 = mxGetPr (pargout [2]) ; + p2 = p1 + nfronts + 1 ; + p3 = p2 + nfronts + 1 ; + p4 = p3 + nfronts + 1 ; + for (i = 0 ; i <= nfronts ; i++) + { + /* convert parent, 1strow, and leftmostdesc to 1-based */ + p1 [i] = (double) (Front_npivcol [i]) ; + p2 [i] = (double) (Front_parent [i] + 1) ; + p3 [i] = (double) (Front_1strow [i] + 1) ; + p4 [i] = (double) (Front_leftmostdesc [i] + 1) ; + } + + /* create Ch */ + pargout [3] = mxCreateDoubleMatrix (nchains+1, 3, mxREAL) ; + p1 = mxGetPr (pargout [3]) ; + p2 = p1 + nchains + 1 ; + p3 = p2 + nchains + 1 ; + for (i = 0 ; i < nchains ; i++) + { + p1 [i] = (double) (Chain_start [i] + 1) ; /* convert to 1-based */ + p2 [i] = (double) (Chain_maxrows [i]) ; + p3 [i] = (double) (Chain_maxcols [i]) ; + } + p1 [nchains] = Chain_start [nchains] + 1 ; + p2 [nchains] = 0 ; + p3 [nchains] = 0 ; + + mxFree (P) ; + mxFree (Q) ; + mxFree (Front_npivcol) ; + mxFree (Front_parent) ; + mxFree (Front_1strow) ; + mxFree (Front_leftmostdesc) ; + mxFree (Chain_start) ; + mxFree (Chain_maxrows) ; + mxFree (Chain_maxcols) ; + } + + /* ---------------------------------------------------------------------- */ + /* report Info */ + /* ---------------------------------------------------------------------- */ + + if (A_is_complex) + { + umfpack_zi_report_info (Control, Info) ; + } + else + { + umfpack_di_report_info (Control, Info) ; + } + + if (do_info > 0) + { + /* return Info */ + pargout [do_info] = mxCreateDoubleMatrix (1, UMFPACK_INFO, mxREAL) ; + OutInfo = mxGetPr (pargout [do_info]) ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + OutInfo [i] = Info [i] ; + } + } +} diff --git a/liboctave/UMFPACK/UMFPACK/MATLAB/west0067.mat b/liboctave/UMFPACK/UMFPACK/MATLAB/west0067.mat new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6cd8c88e60af494ac87bc8fe50c3d1e0ba24409f GIT binary patch literal 4456 zc$~dg2T)X36n%?QR5~hHAS)_}F1Sb$R^U-ASP-HR$C8K$mIPFaT{8AK5{LySniwpo zL+mjQhzmTh1ByT_U>hunktk}$i6I)zee8Xobr+49iT>s6zvtd_?|b+C_dkEbf+9x* z1efZG=G}zSe70$>TS0$2lVP{;i$)LWu$iaHhM zTcd4`c`D574&c|4Vr~yWFXTMGC%^?cui*sfjhxr%gLX@EYw22Bpnm}BJE3ibx&fHq z1#KJ58}OQX4uB7c=DzL*a3sxp$sXhWqbh=k@ynJdpF+N`NPFUfT=pmU?o=>*9jz-v@QvAAtH^Xvz`Fh~I_bXzs69wjTpV%u3tQUymD6n=Q*6)G& zP8bvG=nV+gT1UafItnhte&N;U(TwW`!AYdk;BdvjqhyG<|I4eqDp&UvX>onFMAP~ z?n_HFI$EO9(ZZtfk4mz>rH5Tqxphv7bgM?k?rq}7H|#-p>hKl5YiO;8(?^;M@V?@@ zep=#fe&AG}Qd(r!VD^<~0nObnTd}tLOPce^u>5xCkI_}#vZqy!G-dTaWEmGu&ep5@ zKl%0elfd&?KC$J(&ji0173IFV;0sCj$fKr?tn`s|g6ryj4LhlhUe6?*;JUgxkJ=6g zKTD8wg6rx;ywam~cyvUzZk%0Qw(hj;5+_!DKGS)6RTMircFDpG+cR0w?CaJ0Gwh{0 zKSxDPRc$Mf^2(MMPG7oU6DyC~{=4zRd{&<1IAQp>L{>V(zufQp3+$vnW>V zt|(4JsXWI)$Hts4!g!B`LS~$+vwuZHLUbrqigEjFIkDY zOIh^IV{ff{g!902^SZoSKRtYPnS+7DdYW$$sjMy7LJR)v(pNdtlNP27Zp_cTMe}k_ zx3O7ZNb?kB8DkxGQ*})byW7t*X|bJo{pT4AY4OKxzq5McK#vYBY484vf;P6dxPRR& zo!-Im1i#xgQSBB`(|liAnvSx+VkGGV*VQ%H*?f3^{0&JbxUTMwrDfXK9>w?5BGI&zv!wT1tP6H5+u~)K#i>N#EG&>sVT1 zUHf#*(P~g+zo--l!07K3iG+Y|@Y3-#?uLinGI^=q~$G4-?P1bIabjbB|cWWi&^u6GfkT z{fW5Xx_ybb;JW>YxZu+B68)E7^|NF1H`tD@-OSEp91UKX9>ywO9B0?7WUMkIb>kr$ pGod4z_ecI7_@>|c?Z~UY_d7yHFua}4g}20Hcr#SO$D98G{0Dc&nZp18 diff --git a/liboctave/UMFPACK/UMFPACK/Makefile b/liboctave/UMFPACK/UMFPACK/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Makefile @@ -0,0 +1,68 @@ +#------------------------------------------------------------------------------- +# UMFPACK makefile (for GNU make or original make) +#------------------------------------------------------------------------------- + +# UMFPACK requires the AMD package to be in ../AMD + +# compile everything (except hb, fortran, and fortran64), including AMD and the +# MATLAB mexFunctions +all: + ( cd ../AMD ; make ) + ( cd Source ; make ) + ( cd Demo ; make ) + ( cd MATLAB ; make ) + - cat Doc/License + +# compile just the C-callable libraries and demo programs (not mexFunctions) +lib: + ( cd ../AMD ; make lib ) + ( cd Source ; make ) + ( cd Demo ; make ) + - cat Doc/License + +# compile the FORTRAN interface and demo program +fortran: + ( cd Demo ; make fortran ) + +# compile the 64-bit FORTRAN interface and demo program +fortran64: + ( cd Demo ; make fortran64 ) + +# compile the Harwell/Boeing demo program +hb: + ( cd Demo ; make hb ) + +# compile a Octave version +# (not compiled by "make all") +octave: + ( cd OCTAVE ; make ) + - cat Doc/License + +# remove object files, but keep the compiled programs and library archives +clean: + ( cd ../AMD ; make clean ) + ( cd Source ; make clean ) + ( cd Demo ; make clean ) + ( cd MATLAB ; make clean ) + ( cd OCTAVE ; make clean ) + ( cd Doc ; make clean ) + +# clean, and then remove compiled programs and library archives +purge: + ( cd ../AMD ; make purge ) + ( cd Source ; make purge ) + ( cd Demo ; make purge ) + ( cd MATLAB ; make purge ) + ( cd OCTAVE ; make purge ) + ( cd Doc ; make purge ) + +# create PDF documents for the original distribution +doc: + ( cd ../AMD ; make doc ) + ( cd Doc ; make ) + +# get ready for distribution +dist: purge + ( cd ../AMD ; make dist ) + ( cd Demo ; make dist ) + ( cd Doc ; make ) diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/Contents.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/Contents.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/Contents.m @@ -0,0 +1,21 @@ +%Contents of the UMFPACK sparse matrix toolbox: +% +% umfpack computes x=A\b, x=A/b, or lu (A) for a sparse matrix A +% umfpack_make to compile umfpack for use in MATLAB +% umfpack_report prints optional control settings and statistics +% umfpack_demo a long demo +% umfpack_simple a simple demo +% umfpack_btf factorize A using a block triangular form +% umfpack_solve x = A\b or x = b/A +% lu_normest estimates norm (L*U-A, 1) without forming L*U-A +% luflop given L and U, computes # of flops required to compute them +% +% See also: +% amd symmetric minimum degree ordering +% colamd unsymmetric column approx minimum degree ordering +% symamd symmetric approx minimum degree ordering, based on colamd +% +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. Type umfpack_details for License. + +help Contents diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/GNUmakefile b/liboctave/UMFPACK/UMFPACK/OCTAVE/GNUmakefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/GNUmakefile @@ -0,0 +1,248 @@ +#------------------------------------------------------------------------------- +# UMFPACK GNUmakefile for the UMFPACK OCTAVE oct-file (GNU "make" only) +#------------------------------------------------------------------------------- + +.PRECIOUS: %.o + +# UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +# Davis. All Rights Reserved. See ../README for License. + +all: umfpack luflop + +include ../Make/Make.include + +MKOCT = mkoctfile $(CONFIG) -DNRECIPROCAL -I/usr/include/atlas -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source + +OCT_SPARSE_INC = -I../../../ + + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- + +# non-user-callable umf_*.[ch] files: +UMFCH = umf_assemble umf_blas3_update \ + umf_build_tuples umf_create_element \ + umf_dump umf_extend_front umf_garbage_collection \ + umf_get_memory umf_init_front umf_kernel \ + umf_kernel_init umf_kernel_wrapup \ + umf_local_search umf_lsolve umf_ltsolve \ + umf_mem_alloc_element umf_mem_alloc_head_block \ + umf_mem_alloc_tail_block umf_mem_free_tail_block \ + umf_mem_init_memoryspace \ + umf_report_vector umf_row_search umf_scale_column \ + umf_set_stats umf_solve umf_symbolic_usage umf_transpose \ + umf_tuple_lengths umf_usolve umf_utsolve umf_valid_numeric \ + umf_valid_symbolic umf_grow_front umf_start_front umf_2by2 \ + umf_store_lu umf_scale + +# non-user-callable umf_*.[ch] files, int/long versions only (no real/complex): +UMFINT = umf_analyze umf_apply_order umf_colamd umf_free umf_fsize \ + umf_is_permutation umf_malloc umf_realloc umf_report_perm \ + umf_singletons + +# non-user-callable and user-callable amd_*.[ch] files (int/long versions only): +AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ + amd_order amd_control amd_info amd_valid + +# non-user-callable, created from umf_ltsolve.c, umf_utsolve.c, +# umf_triplet.c, and umf_assemble.c , with int/long and real/complex versions: +UMF_CREATED = umf_lhsolve umf_uhsolve umf_triplet_map_nox \ + umf_triplet_nomap_x umf_triplet_nomap_nox umf_triplet_map_x \ + umf_assemble_fixq umf_store_lu_drop + +# non-user-callable, int/long and real/complex versions: +UMF = $(UMF_CREATED) $(UMFCH) + +# user-callable umfpack_*.[ch] files (int/long and real/complex): +UMFPACK = umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ + umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ + umfpack_get_symbolic umfpack_get_determinant umfpack_numeric \ + umfpack_qsymbolic umfpack_report_control umfpack_report_info \ + umfpack_report_matrix umfpack_report_numeric umfpack_report_perm \ + umfpack_report_status umfpack_report_symbolic umfpack_report_triplet \ + umfpack_report_vector umfpack_solve umfpack_symbolic \ + umfpack_transpose umfpack_triplet_to_col umfpack_scale \ + umfpack_load_numeric umfpack_save_numeric \ + umfpack_load_symbolic umfpack_save_symbolic + +# user-callable, created from umfpack_solve.c (umfpack_wsolve.h exists, though): +# with int/long and real/complex versions: +UMFPACKW = umfpack_wsolve + +USER = $(UMFPACKW) $(UMFPACK) + +# user-callable, only one version for int/long, real/complex, *.[ch] files: +GENERIC = umfpack_timer umfpack_tictoc + +#------------------------------------------------------------------------------- +# include files: +#------------------------------------------------------------------------------- + +AMDH = ../../AMD/Source/amd_internal.h ../../AMD/Include/amd.h + +INC1 = umf_config.h umf_version.h umf_internal.h umf_triplet.h + +INC = ../Include/umfpack.h \ + $(addprefix ../Source/, $(INC1)) \ + $(addprefix ../Source/, $(addsuffix .h,$(UMFCH))) \ + $(addprefix ../Source/, $(addsuffix .h,$(UMFINT))) \ + $(addprefix ../Include/, $(addsuffix .h,$(USER))) \ + $(addprefix ../Include/, $(addsuffix .h,$(GENERIC))) \ + $(AMDH) + +#------------------------------------------------------------------------------- +# Create the umfpack and amd oct-file for OCTAVE (int versions only) +#------------------------------------------------------------------------------- + +OCTI = $(addsuffix .o, $(subst umf_,umf_o_,$(UMFINT))) +OCTDI = $(addsuffix .o, $(subst umf_,umf_od_,$(UMF)) $(subst umfpack_,umfpack_od_,$(USER))) +OCTZI = $(addsuffix .o, $(subst umf_,umf_oz_,$(UMF)) $(subst umfpack_,umfpack_oz_,$(USER)) ) +OCTAMD = $(addsuffix .o, $(subst amd_,amd_o_,$(AMD))) +OCTGN = $(addsuffix .o, $(subst umfpack_,umfpack_o_,$(GENERIC))) + +OCTUMFPACK = $(OCTI) $(OCTDI) $(OCTZI) $(OCTGN) + +OCTUMFPACK_LIB = umfpack_octave.o + +# Note that mkoctfile has an "-o" option, but it doesn't work in conjunction +# with the "-c" option, thus the need for $(MV) commands. +# If it did, then the rules would be much simpler: +# $(MKOCT) -DDINT -c $< -o $@ + +#---------------------------------------- +# integer-only routines (no real/complex): +#---------------------------------------- + +amd_o_%.o: ../../AMD/Source/amd_%.c $(AMDH) + $(MKOCT) -DDINT -c $< + - $(MV) ../../AMD/Source/amd_$*.o $@ + + +umf_o_%.o: ../Source/umf_%.c $(INC) + $(MKOCT) -DDINT -c $< + - $(MV) ../Source/umf_$*.o $@ + +#---------------------------------------- +# Double precision, int version, for OCTAVE +#---------------------------------------- + +umf_od_%.o: ../Source/umf_%.c $(INC) + $(MKOCT) -DDINT -c $< + - $(MV) ../Source/umf_$*.o $@ + +umf_od_%hsolve.o: ../Source/umf_%tsolve.c $(INC) + $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c $< + - $(MV) ../Source/umf_$*tsolve.o $@ + +umf_od_triplet_map_x.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DDINT -DDO_MAP -DDO_VALUES -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_od_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DDINT -DDO_MAP -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_od_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DDINT -DDO_VALUES -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_od_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DDINT -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_od_assemble_fixq.o: ../Source/umf_assemble.c $(INC) + $(MKOCT) -DDINT -DFIXQ -c $< + - $(MV) ../Source/umf_assemble.o $@ + +umf_od_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) + $(MKOCT) -DDINT -DDROP -c $< + - $(MV) ../Source/umf_store_lu.o $@ + +umfpack_od_wsolve.o: ../Source/umfpack_solve.c $(INC) + $(MKOCT) -DDINT -DWSOLVE -c $< + - $(MV) ../Source/umfpack_solve.o $@ + +umfpack_od_%.o: ../Source/umfpack_%.c $(INC) + $(MKOCT) -DDINT -c $< + - $(MV) ../Source/umfpack_$*.o $@ + +#---------------------------------------- +# Complex double precision, int version, for OCTAVE +#---------------------------------------- + +umf_oz_%.o: ../Source/umf_%.c $(INC) + $(MKOCT) -DZINT -c $< + - $(MV) ../Source/umf_$*.o $@ + +umf_oz_%hsolve.o: ../Source/umf_%tsolve.c $(INC) + $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c $< + - $(MV) ../Source/umf_$*tsolve.o $@ + +umf_oz_triplet_map_x.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DZINT -DDO_MAP -DDO_VALUES -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_oz_triplet_map_nox.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DZINT -DDO_MAP -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_oz_triplet_nomap_x.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DZINT -DDO_VALUES -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_oz_triplet_nomap_nox.o: ../Source/umf_triplet.c $(INC) + $(MKOCT) -DZINT -c $< + - $(MV) ../Source/umf_triplet.o $@ + +umf_oz_assemble_fixq.o: ../Source/umf_assemble.c $(INC) + $(MKOCT) -DZINT -DFIXQ -c $< + - $(MV) ../Source/umf_assemble.o $@ + +umf_oz_store_lu_drop.o: ../Source/umf_store_lu.c $(INC) + $(MKOCT) -DZINT -DDROP -c $< + - $(MV) ../Source/umf_store_lu.o $@ + +umfpack_oz_wsolve.o: ../Source/umfpack_solve.c $(INC) + $(MKOCT) -DZINT -DWSOLVE -c $< + - $(MV) ../Source/umfpack_solve.o $@ + +umfpack_oz_%.o: ../Source/umfpack_%.c $(INC) + $(MKOCT) -DZINT -c $< + - $(MV) ../Source/umfpack_$*.o $@ + +#---------------------------------------- +# Generic routines for OCTAVE +#---------------------------------------- + +umfpack_o_timer.o: ../Source/umfpack_timer.c $(INC) + $(MKOCT) -c $< + - $(MV) ../Source/umfpack_timer.o $@ + +umfpack_o_tictoc.o: ../Source/umfpack_tictoc.c $(INC) + $(MKOCT) -c $< + - $(MV) ../Source/umfpack_tictoc.o $@ + +#---------------------------------------- +# umfpack oct-files +#---------------------------------------- + +umfpack: umfpack.cc $(OCTUMFPACK) $(OCTAMD) + $(MKOCT) $(OCT_SPARSE_INC) umfpack.cc $(OCTUMFPACK) $(OCTAMD) -o umfpack.oct + +luflop: luflop.cc + $(MKOCT) $(OCT_SPARSE_INC) luflop.cc -o luflop.oct + +#---------------------------------------- +# umfpack library to link with octave +#---------------------------------------- + +octave: $(OCTUMFPACK) $(OCTAMD) + ld -r $(OCTUMFPACK) $(OCTAMD) -o ../../../$(OCTUMFPACK_LIB) + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) *.oct *.so diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/Makefile b/liboctave/UMFPACK/UMFPACK/OCTAVE/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/Makefile @@ -0,0 +1,517 @@ +#------------------------------------------------------------------------------- +# UMFPACK Makefile for the UMFPACK MATLAB mexFunction (old "make" only) +#------------------------------------------------------------------------------- + +# UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +# Davis. All Rights Reserved. See ../README for License. + +# This is a very ugly Makefile, and is only provided for those who do not +# have GNU make. Note that it is not used if you have GNU make. It ignores +# dependency checking and just compiles everything. It was created +# automatically, via make -n using the GNUmakefile. That way, I don't have +# maintain two Makefiles. + +all: umfpack luflop + +include ../Make/Make.include + +MKOCT = mkoctfile $(CONFIG) -DNRECIPROCAL -I/usr/include/atlas -I../Include -I../Source -I../../AMD/Include -I../../AMD/Source + +OCT_SPARSE_INC = -I../../../ +OCTUMFPACK_LIB = umfpack_octave.o + +umfpack: + $(MKOCT) -DDINT -c ../Source/umf_analyze.c + $(MV) -f ../Source/umf_analyze.o umf_m_analyze.o + $(MKOCT) -DDINT -c ../Source/umf_apply_order.c + $(MV) -f ../Source/umf_apply_order.o umf_m_apply_order.o + $(MKOCT) -DDINT -c ../Source/umf_colamd.c + $(MV) -f ../Source/umf_colamd.o umf_m_colamd.o + $(MKOCT) -DDINT -c ../Source/umf_free.c + $(MV) -f ../Source/umf_free.o umf_m_free.o + $(MKOCT) -DDINT -c ../Source/umf_fsize.c + $(MV) -f ../Source/umf_fsize.o umf_m_fsize.o + $(MKOCT) -DDINT -c ../Source/umf_is_permutation.c + $(MV) -f ../Source/umf_is_permutation.o umf_m_is_permutation.o + $(MKOCT) -DDINT -c ../Source/umf_malloc.c + $(MV) -f ../Source/umf_malloc.o umf_m_malloc.o + $(MKOCT) -DDINT -c ../Source/umf_realloc.c + $(MV) -f ../Source/umf_realloc.o umf_m_realloc.o + $(MKOCT) -DDINT -c ../Source/umf_report_perm.c + $(MV) -f ../Source/umf_report_perm.o umf_m_report_perm.o + $(MKOCT) -DDINT -c ../Source/umf_singletons.c + $(MV) -f ../Source/umf_singletons.o umf_m_singletons.o + $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c + $(MV) -f ../Source/umf_ltsolve.o umf_od_lhsolve.o + $(MKOCT) -DDINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c + $(MV) -f ../Source/umf_utsolve.o umf_od_uhsolve.o + $(MKOCT) -DDINT -DDO_MAP -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_od_triplet_map_nox.o + $(MKOCT) -DDINT -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_od_triplet_nomap_x.o + $(MKOCT) -DDINT -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_od_triplet_nomap_nox.o + $(MKOCT) -DDINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_od_triplet_map_x.o + $(MKOCT) -DDINT -DFIXQ -c ../Source/umf_assemble.c + $(MV) -f ../Source/umf_assemble.o umf_od_assemble_fixq.o + $(MKOCT) -DDINT -DDROP -c ../Source/umf_store_lu.c + $(MV) -f ../Source/umf_store_lu.o umf_od_store_lu_drop.o + $(MKOCT) -DDINT -c ../Source/umf_assemble.c + $(MV) -f ../Source/umf_assemble.o umf_od_assemble.o + $(MKOCT) -DDINT -c ../Source/umf_blas3_update.c + $(MV) -f ../Source/umf_blas3_update.o umf_od_blas3_update.o + $(MKOCT) -DDINT -c ../Source/umf_build_tuples.c + $(MV) -f ../Source/umf_build_tuples.o umf_od_build_tuples.o + $(MKOCT) -DDINT -c ../Source/umf_create_element.c + $(MV) -f ../Source/umf_create_element.o umf_od_create_element.o + $(MKOCT) -DDINT -c ../Source/umf_dump.c + $(MV) -f ../Source/umf_dump.o umf_od_dump.o + $(MKOCT) -DDINT -c ../Source/umf_extend_front.c + $(MV) -f ../Source/umf_extend_front.o umf_od_extend_front.o + $(MKOCT) -DDINT -c ../Source/umf_garbage_collection.c + $(MV) -f ../Source/umf_garbage_collection.o umf_od_garbage_collection.o + $(MKOCT) -DDINT -c ../Source/umf_get_memory.c + $(MV) -f ../Source/umf_get_memory.o umf_od_get_memory.o + $(MKOCT) -DDINT -c ../Source/umf_init_front.c + $(MV) -f ../Source/umf_init_front.o umf_od_init_front.o + $(MKOCT) -DDINT -c ../Source/umf_kernel.c + $(MV) -f ../Source/umf_kernel.o umf_od_kernel.o + $(MKOCT) -DDINT -c ../Source/umf_kernel_init.c + $(MV) -f ../Source/umf_kernel_init.o umf_od_kernel_init.o + $(MKOCT) -DDINT -c ../Source/umf_kernel_wrapup.c + $(MV) -f ../Source/umf_kernel_wrapup.o umf_od_kernel_wrapup.o + $(MKOCT) -DDINT -c ../Source/umf_local_search.c + $(MV) -f ../Source/umf_local_search.o umf_od_local_search.o + $(MKOCT) -DDINT -c ../Source/umf_lsolve.c + $(MV) -f ../Source/umf_lsolve.o umf_od_lsolve.o + $(MKOCT) -DDINT -c ../Source/umf_ltsolve.c + $(MV) -f ../Source/umf_ltsolve.o umf_od_ltsolve.o + $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_element.c + $(MV) -f ../Source/umf_mem_alloc_element.o umf_od_mem_alloc_element.o + $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_head_block.c + $(MV) -f ../Source/umf_mem_alloc_head_block.o umf_od_mem_alloc_head_block.o + $(MKOCT) -DDINT -c ../Source/umf_mem_alloc_tail_block.c + $(MV) -f ../Source/umf_mem_alloc_tail_block.o umf_od_mem_alloc_tail_block.o + $(MKOCT) -DDINT -c ../Source/umf_mem_free_tail_block.c + $(MV) -f ../Source/umf_mem_free_tail_block.o umf_od_mem_free_tail_block.o + $(MKOCT) -DDINT -c ../Source/umf_mem_init_memoryspace.c + $(MV) -f ../Source/umf_mem_init_memoryspace.o umf_od_mem_init_memoryspace.o + $(MKOCT) -DDINT -c ../Source/umf_report_vector.c + $(MV) -f ../Source/umf_report_vector.o umf_od_report_vector.o + $(MKOCT) -DDINT -c ../Source/umf_row_search.c + $(MV) -f ../Source/umf_row_search.o umf_od_row_search.o + $(MKOCT) -DDINT -c ../Source/umf_scale_column.c + $(MV) -f ../Source/umf_scale_column.o umf_od_scale_column.o + $(MKOCT) -DDINT -c ../Source/umf_set_stats.c + $(MV) -f ../Source/umf_set_stats.o umf_od_set_stats.o + $(MKOCT) -DDINT -c ../Source/umf_solve.c + $(MV) -f ../Source/umf_solve.o umf_od_solve.o + $(MKOCT) -DDINT -c ../Source/umf_symbolic_usage.c + $(MV) -f ../Source/umf_symbolic_usage.o umf_od_symbolic_usage.o + $(MKOCT) -DDINT -c ../Source/umf_transpose.c + $(MV) -f ../Source/umf_transpose.o umf_od_transpose.o + $(MKOCT) -DDINT -c ../Source/umf_tuple_lengths.c + $(MV) -f ../Source/umf_tuple_lengths.o umf_od_tuple_lengths.o + $(MKOCT) -DDINT -c ../Source/umf_usolve.c + $(MV) -f ../Source/umf_usolve.o umf_od_usolve.o + $(MKOCT) -DDINT -c ../Source/umf_utsolve.c + $(MV) -f ../Source/umf_utsolve.o umf_od_utsolve.o + $(MKOCT) -DDINT -c ../Source/umf_valid_numeric.c + $(MV) -f ../Source/umf_valid_numeric.o umf_od_valid_numeric.o + $(MKOCT) -DDINT -c ../Source/umf_valid_symbolic.c + $(MV) -f ../Source/umf_valid_symbolic.o umf_od_valid_symbolic.o + $(MKOCT) -DDINT -c ../Source/umf_grow_front.c + $(MV) -f ../Source/umf_grow_front.o umf_od_grow_front.o + $(MKOCT) -DDINT -c ../Source/umf_start_front.c + $(MV) -f ../Source/umf_start_front.o umf_od_start_front.o + $(MKOCT) -DDINT -c ../Source/umf_2by2.c + $(MV) -f ../Source/umf_2by2.o umf_od_2by2.o + $(MKOCT) -DDINT -c ../Source/umf_store_lu.c + $(MV) -f ../Source/umf_store_lu.o umf_od_store_lu.o + $(MKOCT) -DDINT -c ../Source/umf_scale.c + $(MV) -f ../Source/umf_scale.o umf_od_scale.o + $(MKOCT) -DDINT -DWSOLVE -c ../Source/umfpack_solve.c + $(MV) -f ../Source/umfpack_solve.o umfpack_od_wsolve.o + $(MKOCT) -DDINT -c ../Source/umfpack_col_to_triplet.c + $(MV) -f ../Source/umfpack_col_to_triplet.o umfpack_od_col_to_triplet.o + $(MKOCT) -DDINT -c ../Source/umfpack_defaults.c + $(MV) -f ../Source/umfpack_defaults.o umfpack_od_defaults.o + $(MKOCT) -DDINT -c ../Source/umfpack_free_numeric.c + $(MV) -f ../Source/umfpack_free_numeric.o umfpack_od_free_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_free_symbolic.c + $(MV) -f ../Source/umfpack_free_symbolic.o umfpack_od_free_symbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_get_numeric.c + $(MV) -f ../Source/umfpack_get_numeric.o umfpack_od_get_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_get_lunz.c + $(MV) -f ../Source/umfpack_get_lunz.o umfpack_od_get_lunz.o + $(MKOCT) -DDINT -c ../Source/umfpack_get_symbolic.c + $(MV) -f ../Source/umfpack_get_symbolic.o umfpack_od_get_symbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_get_determinant.c + $(MV) -f ../Source/umfpack_get_determinant.o umfpack_od_get_determinant.o + $(MKOCT) -DDINT -c ../Source/umfpack_numeric.c + $(MV) -f ../Source/umfpack_numeric.o umfpack_od_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_qsymbolic.c + $(MV) -f ../Source/umfpack_qsymbolic.o umfpack_od_qsymbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_control.c + $(MV) -f ../Source/umfpack_report_control.o umfpack_od_report_control.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_info.c + $(MV) -f ../Source/umfpack_report_info.o umfpack_od_report_info.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_matrix.c + $(MV) -f ../Source/umfpack_report_matrix.o umfpack_od_report_matrix.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_numeric.c + $(MV) -f ../Source/umfpack_report_numeric.o umfpack_od_report_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_perm.c + $(MV) -f ../Source/umfpack_report_perm.o umfpack_od_report_perm.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_status.c + $(MV) -f ../Source/umfpack_report_status.o umfpack_od_report_status.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_symbolic.c + $(MV) -f ../Source/umfpack_report_symbolic.o umfpack_od_report_symbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_triplet.c + $(MV) -f ../Source/umfpack_report_triplet.o umfpack_od_report_triplet.o + $(MKOCT) -DDINT -c ../Source/umfpack_report_vector.c + $(MV) -f ../Source/umfpack_report_vector.o umfpack_od_report_vector.o + $(MKOCT) -DDINT -c ../Source/umfpack_solve.c + $(MV) -f ../Source/umfpack_solve.o umfpack_od_solve.o + $(MKOCT) -DDINT -c ../Source/umfpack_symbolic.c + $(MV) -f ../Source/umfpack_symbolic.o umfpack_od_symbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_transpose.c + $(MV) -f ../Source/umfpack_transpose.o umfpack_od_transpose.o + $(MKOCT) -DDINT -c ../Source/umfpack_triplet_to_col.c + $(MV) -f ../Source/umfpack_triplet_to_col.o umfpack_od_triplet_to_col.o + $(MKOCT) -DDINT -c ../Source/umfpack_scale.c + $(MV) -f ../Source/umfpack_scale.o umfpack_od_scale.o + $(MKOCT) -DDINT -c ../Source/umfpack_load_numeric.c + $(MV) -f ../Source/umfpack_load_numeric.o umfpack_od_load_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_save_numeric.c + $(MV) -f ../Source/umfpack_save_numeric.o umfpack_od_save_numeric.o + $(MKOCT) -DDINT -c ../Source/umfpack_load_symbolic.c + $(MV) -f ../Source/umfpack_load_symbolic.o umfpack_od_load_symbolic.o + $(MKOCT) -DDINT -c ../Source/umfpack_save_symbolic.c + $(MV) -f ../Source/umfpack_save_symbolic.o umfpack_od_save_symbolic.o + $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_ltsolve.c + $(MV) -f ../Source/umf_ltsolve.o umf_oz_lhsolve.o + $(MKOCT) -DZINT -DCONJUGATE_SOLVE -c ../Source/umf_utsolve.c + $(MV) -f ../Source/umf_utsolve.o umf_oz_uhsolve.o + $(MKOCT) -DZINT -DDO_MAP -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_map_nox.o + $(MKOCT) -DZINT -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_nomap_x.o + $(MKOCT) -DZINT -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_nomap_nox.o + $(MKOCT) -DZINT -DDO_MAP -DDO_VALUES -c ../Source/umf_triplet.c + $(MV) -f ../Source/umf_triplet.o umf_oz_triplet_map_x.o + $(MKOCT) -DZINT -DFIXQ -c ../Source/umf_assemble.c + $(MV) -f ../Source/umf_assemble.o umf_oz_assemble_fixq.o + $(MKOCT) -DZINT -DDROP -c ../Source/umf_store_lu.c + $(MV) -f ../Source/umf_store_lu.o umf_oz_store_lu_drop.o + $(MKOCT) -DZINT -c ../Source/umf_assemble.c + $(MV) -f ../Source/umf_assemble.o umf_oz_assemble.o + $(MKOCT) -DZINT -c ../Source/umf_blas3_update.c + $(MV) -f ../Source/umf_blas3_update.o umf_oz_blas3_update.o + $(MKOCT) -DZINT -c ../Source/umf_build_tuples.c + $(MV) -f ../Source/umf_build_tuples.o umf_oz_build_tuples.o + $(MKOCT) -DZINT -c ../Source/umf_create_element.c + $(MV) -f ../Source/umf_create_element.o umf_oz_create_element.o + $(MKOCT) -DZINT -c ../Source/umf_dump.c + $(MV) -f ../Source/umf_dump.o umf_oz_dump.o + $(MKOCT) -DZINT -c ../Source/umf_extend_front.c + $(MV) -f ../Source/umf_extend_front.o umf_oz_extend_front.o + $(MKOCT) -DZINT -c ../Source/umf_garbage_collection.c + $(MV) -f ../Source/umf_garbage_collection.o umf_oz_garbage_collection.o + $(MKOCT) -DZINT -c ../Source/umf_get_memory.c + $(MV) -f ../Source/umf_get_memory.o umf_oz_get_memory.o + $(MKOCT) -DZINT -c ../Source/umf_init_front.c + $(MV) -f ../Source/umf_init_front.o umf_oz_init_front.o + $(MKOCT) -DZINT -c ../Source/umf_kernel.c + $(MV) -f ../Source/umf_kernel.o umf_oz_kernel.o + $(MKOCT) -DZINT -c ../Source/umf_kernel_init.c + $(MV) -f ../Source/umf_kernel_init.o umf_oz_kernel_init.o + $(MKOCT) -DZINT -c ../Source/umf_kernel_wrapup.c + $(MV) -f ../Source/umf_kernel_wrapup.o umf_oz_kernel_wrapup.o + $(MKOCT) -DZINT -c ../Source/umf_local_search.c + $(MV) -f ../Source/umf_local_search.o umf_oz_local_search.o + $(MKOCT) -DZINT -c ../Source/umf_lsolve.c + $(MV) -f ../Source/umf_lsolve.o umf_oz_lsolve.o + $(MKOCT) -DZINT -c ../Source/umf_ltsolve.c + $(MV) -f ../Source/umf_ltsolve.o umf_oz_ltsolve.o + $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_element.c + $(MV) -f ../Source/umf_mem_alloc_element.o umf_oz_mem_alloc_element.o + $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_head_block.c + $(MV) -f ../Source/umf_mem_alloc_head_block.o umf_oz_mem_alloc_head_block.o + $(MKOCT) -DZINT -c ../Source/umf_mem_alloc_tail_block.c + $(MV) -f ../Source/umf_mem_alloc_tail_block.o umf_oz_mem_alloc_tail_block.o + $(MKOCT) -DZINT -c ../Source/umf_mem_free_tail_block.c + $(MV) -f ../Source/umf_mem_free_tail_block.o umf_oz_mem_free_tail_block.o + $(MKOCT) -DZINT -c ../Source/umf_mem_init_memoryspace.c + $(MV) -f ../Source/umf_mem_init_memoryspace.o umf_oz_mem_init_memoryspace.o + $(MKOCT) -DZINT -c ../Source/umf_report_vector.c + $(MV) -f ../Source/umf_report_vector.o umf_oz_report_vector.o + $(MKOCT) -DZINT -c ../Source/umf_row_search.c + $(MV) -f ../Source/umf_row_search.o umf_oz_row_search.o + $(MKOCT) -DZINT -c ../Source/umf_scale_column.c + $(MV) -f ../Source/umf_scale_column.o umf_oz_scale_column.o + $(MKOCT) -DZINT -c ../Source/umf_set_stats.c + $(MV) -f ../Source/umf_set_stats.o umf_oz_set_stats.o + $(MKOCT) -DZINT -c ../Source/umf_solve.c + $(MV) -f ../Source/umf_solve.o umf_oz_solve.o + $(MKOCT) -DZINT -c ../Source/umf_symbolic_usage.c + $(MV) -f ../Source/umf_symbolic_usage.o umf_oz_symbolic_usage.o + $(MKOCT) -DZINT -c ../Source/umf_transpose.c + $(MV) -f ../Source/umf_transpose.o umf_oz_transpose.o + $(MKOCT) -DZINT -c ../Source/umf_tuple_lengths.c + $(MV) -f ../Source/umf_tuple_lengths.o umf_oz_tuple_lengths.o + $(MKOCT) -DZINT -c ../Source/umf_usolve.c + $(MV) -f ../Source/umf_usolve.o umf_oz_usolve.o + $(MKOCT) -DZINT -c ../Source/umf_utsolve.c + $(MV) -f ../Source/umf_utsolve.o umf_oz_utsolve.o + $(MKOCT) -DZINT -c ../Source/umf_valid_numeric.c + $(MV) -f ../Source/umf_valid_numeric.o umf_oz_valid_numeric.o + $(MKOCT) -DZINT -c ../Source/umf_valid_symbolic.c + $(MV) -f ../Source/umf_valid_symbolic.o umf_oz_valid_symbolic.o + $(MKOCT) -DZINT -c ../Source/umf_grow_front.c + $(MV) -f ../Source/umf_grow_front.o umf_oz_grow_front.o + $(MKOCT) -DZINT -c ../Source/umf_start_front.c + $(MV) -f ../Source/umf_start_front.o umf_oz_start_front.o + $(MKOCT) -DZINT -c ../Source/umf_2by2.c + $(MV) -f ../Source/umf_2by2.o umf_oz_2by2.o + $(MKOCT) -DZINT -c ../Source/umf_store_lu.c + $(MV) -f ../Source/umf_store_lu.o umf_oz_store_lu.o + $(MKOCT) -DZINT -c ../Source/umf_scale.c + $(MV) -f ../Source/umf_scale.o umf_oz_scale.o + $(MKOCT) -DZINT -DWSOLVE -c ../Source/umfpack_solve.c + $(MV) -f ../Source/umfpack_solve.o umfpack_oz_wsolve.o + $(MKOCT) -DZINT -c ../Source/umfpack_col_to_triplet.c + $(MV) -f ../Source/umfpack_col_to_triplet.o umfpack_oz_col_to_triplet.o + $(MKOCT) -DZINT -c ../Source/umfpack_defaults.c + $(MV) -f ../Source/umfpack_defaults.o umfpack_oz_defaults.o + $(MKOCT) -DZINT -c ../Source/umfpack_free_numeric.c + $(MV) -f ../Source/umfpack_free_numeric.o umfpack_oz_free_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_free_symbolic.c + $(MV) -f ../Source/umfpack_free_symbolic.o umfpack_oz_free_symbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_get_numeric.c + $(MV) -f ../Source/umfpack_get_numeric.o umfpack_oz_get_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_get_lunz.c + $(MV) -f ../Source/umfpack_get_lunz.o umfpack_oz_get_lunz.o + $(MKOCT) -DZINT -c ../Source/umfpack_get_symbolic.c + $(MV) -f ../Source/umfpack_get_symbolic.o umfpack_oz_get_symbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_get_determinant.c + $(MV) -f ../Source/umfpack_get_determinant.o umfpack_oz_get_determinant.o + $(MKOCT) -DZINT -c ../Source/umfpack_numeric.c + $(MV) -f ../Source/umfpack_numeric.o umfpack_oz_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_qsymbolic.c + $(MV) -f ../Source/umfpack_qsymbolic.o umfpack_oz_qsymbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_control.c + $(MV) -f ../Source/umfpack_report_control.o umfpack_oz_report_control.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_info.c + $(MV) -f ../Source/umfpack_report_info.o umfpack_oz_report_info.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_matrix.c + $(MV) -f ../Source/umfpack_report_matrix.o umfpack_oz_report_matrix.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_numeric.c + $(MV) -f ../Source/umfpack_report_numeric.o umfpack_oz_report_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_perm.c + $(MV) -f ../Source/umfpack_report_perm.o umfpack_oz_report_perm.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_status.c + $(MV) -f ../Source/umfpack_report_status.o umfpack_oz_report_status.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_symbolic.c + $(MV) -f ../Source/umfpack_report_symbolic.o umfpack_oz_report_symbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_triplet.c + $(MV) -f ../Source/umfpack_report_triplet.o umfpack_oz_report_triplet.o + $(MKOCT) -DZINT -c ../Source/umfpack_report_vector.c + $(MV) -f ../Source/umfpack_report_vector.o umfpack_oz_report_vector.o + $(MKOCT) -DZINT -c ../Source/umfpack_solve.c + $(MV) -f ../Source/umfpack_solve.o umfpack_oz_solve.o + $(MKOCT) -DZINT -c ../Source/umfpack_symbolic.c + $(MV) -f ../Source/umfpack_symbolic.o umfpack_oz_symbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_transpose.c + $(MV) -f ../Source/umfpack_transpose.o umfpack_oz_transpose.o + $(MKOCT) -DZINT -c ../Source/umfpack_triplet_to_col.c + $(MV) -f ../Source/umfpack_triplet_to_col.o umfpack_oz_triplet_to_col.o + $(MKOCT) -DZINT -c ../Source/umfpack_scale.c + $(MV) -f ../Source/umfpack_scale.o umfpack_oz_scale.o + $(MKOCT) -DZINT -c ../Source/umfpack_load_numeric.c + $(MV) -f ../Source/umfpack_load_numeric.o umfpack_oz_load_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_save_numeric.c + $(MV) -f ../Source/umfpack_save_numeric.o umfpack_oz_save_numeric.o + $(MKOCT) -DZINT -c ../Source/umfpack_load_symbolic.c + $(MV) -f ../Source/umfpack_load_symbolic.o umfpack_oz_load_symbolic.o + $(MKOCT) -DZINT -c ../Source/umfpack_save_symbolic.c + $(MV) -f ../Source/umfpack_save_symbolic.o umfpack_oz_save_symbolic.o + $(MKOCT) -c ../Source/umfpack_timer.c + $(MV) -f ../Source/umfpack_timer.o umfpack_m_timer.o + $(MKOCT) -c ../Source/umfpack_tictoc.c + $(MV) -f ../Source/umfpack_tictoc.o umfpack_m_tictoc.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_aat.c + $(MV) -f ../../AMD/Source/amd_aat.o amd_m_aat.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_1.c + $(MV) -f ../../AMD/Source/amd_1.o amd_m_1.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_2.c + $(MV) -f ../../AMD/Source/amd_2.o amd_m_2.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_dump.c + $(MV) -f ../../AMD/Source/amd_dump.o amd_m_dump.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_postorder.c + $(MV) -f ../../AMD/Source/amd_postorder.o amd_m_postorder.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_post_tree.c + $(MV) -f ../../AMD/Source/amd_post_tree.o amd_m_post_tree.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_defaults.c + $(MV) -f ../../AMD/Source/amd_defaults.o amd_m_defaults.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_order.c + $(MV) -f ../../AMD/Source/amd_order.o amd_m_order.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_control.c + $(MV) -f ../../AMD/Source/amd_control.o amd_m_control.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_info.c + $(MV) -f ../../AMD/Source/amd_info.o amd_m_info.o + $(MKOCT) -DDINT -c ../../AMD/Source/amd_valid.c + $(MV) -f ../../AMD/Source/amd_valid.o amd_m_valid.o + $(MKOCT) -o umfpack.oct $(OCT_SPARSE_INC) umfpack.cc \ + umf_o_analyze.o umf_o_apply_order.o umf_o_colamd.o umf_o_free.o \ + umf_o_fsize.o umf_o_is_permutation.o umf_o_malloc.o \ + umf_o_realloc.o umf_o_report_perm.o umf_o_singletons.o \ + umf_od_lhsolve.o umf_od_uhsolve.o umf_od_triplet_map_nox.o \ + umf_od_triplet_nomap_x.o umf_od_triplet_nomap_nox.o \ + umf_od_triplet_map_x.o umf_od_assemble_fixq.o \ + umf_od_store_lu_drop.o umf_od_assemble.o umf_od_blas3_update.o \ + umf_od_build_tuples.o umf_od_create_element.o umf_od_dump.o \ + umf_od_extend_front.o umf_od_garbage_collection.o \ + umf_od_get_memory.o umf_od_init_front.o umf_od_kernel.o \ + umf_od_kernel_init.o umf_od_kernel_wrapup.o umf_od_local_search.o \ + umf_od_lsolve.o umf_od_ltsolve.o umf_od_mem_alloc_element.o \ + umf_od_mem_alloc_head_block.o umf_od_mem_alloc_tail_block.o \ + umf_od_mem_free_tail_block.o umf_od_mem_init_memoryspace.o \ + umf_od_report_vector.o umf_od_row_search.o umf_od_scale_column.o \ + umf_od_set_stats.o umf_od_solve.o umf_od_symbolic_usage.o \ + umf_od_transpose.o umf_od_tuple_lengths.o umf_od_usolve.o \ + umf_od_utsolve.o umf_od_valid_numeric.o umf_od_valid_symbolic.o \ + umf_od_grow_front.o umf_od_start_front.o umf_od_2by2.o \ + umf_od_store_lu.o umf_od_scale.o umfpack_od_wsolve.o \ + umfpack_od_col_to_triplet.o umfpack_od_defaults.o \ + umfpack_od_free_numeric.o umfpack_od_free_symbolic.o \ + umfpack_od_get_numeric.o umfpack_od_get_lunz.o \ + umfpack_od_get_symbolic.o umfpack_od_numeric.o \ + umfpack_od_qsymbolic.o umfpack_od_report_control.o \ + umfpack_od_report_info.o umfpack_od_report_matrix.o \ + umfpack_od_report_numeric.o umfpack_od_report_perm.o \ + umfpack_od_report_status.o umfpack_od_report_symbolic.o \ + umfpack_od_report_triplet.o umfpack_od_report_vector.o \ + umfpack_od_solve.o umfpack_od_symbolic.o umfpack_od_transpose.o \ + umfpack_od_triplet_to_col.o umfpack_od_scale.o \ + umfpack_od_load_numeric.o umfpack_od_save_numeric.o \ + umfpack_od_load_symbolic.o umfpack_od_save_symbolic.o \ + umf_oz_lhsolve.o umf_oz_uhsolve.o umf_oz_triplet_map_nox.o \ + umf_oz_triplet_nomap_x.o umf_oz_triplet_nomap_nox.o \ + umf_oz_triplet_map_x.o umf_oz_assemble_fixq.o \ + umf_oz_store_lu_drop.o umf_oz_assemble.o umf_oz_blas3_update.o \ + umf_oz_build_tuples.o umf_oz_create_element.o umf_oz_dump.o \ + umf_oz_extend_front.o umf_oz_garbage_collection.o \ + umf_oz_get_memory.o umf_oz_init_front.o umf_oz_kernel.o \ + umf_oz_kernel_init.o umf_oz_kernel_wrapup.o umf_oz_local_search.o \ + umf_oz_lsolve.o umf_oz_ltsolve.o umf_oz_mem_alloc_element.o \ + umf_oz_mem_alloc_head_block.o umf_oz_mem_alloc_tail_block.o \ + umf_oz_mem_free_tail_block.o umf_oz_mem_init_memoryspace.o \ + umf_oz_report_vector.o umf_oz_row_search.o umf_oz_scale_column.o \ + umf_oz_set_stats.o umf_oz_solve.o umf_oz_symbolic_usage.o \ + umf_oz_transpose.o umf_oz_tuple_lengths.o umf_oz_usolve.o \ + umf_oz_utsolve.o umf_oz_valid_numeric.o umf_oz_valid_symbolic.o \ + umf_oz_grow_front.o umf_oz_start_front.o umf_oz_2by2.o \ + umf_oz_store_lu.o umf_oz_scale.o umfpack_oz_wsolve.o \ + umfpack_oz_col_to_triplet.o umfpack_oz_defaults.o \ + umfpack_oz_free_numeric.o umfpack_oz_free_symbolic.o \ + umfpack_oz_get_numeric.o umfpack_oz_get_lunz.o \ + umfpack_oz_get_symbolic.o umfpack_oz_numeric.o \ + umfpack_oz_qsymbolic.o umfpack_oz_report_control.o \ + umfpack_oz_report_info.o umfpack_oz_report_matrix.o \ + umfpack_oz_report_numeric.o umfpack_oz_report_perm.o \ + umfpack_oz_report_status.o umfpack_oz_report_symbolic.o \ + umfpack_oz_report_triplet.o umfpack_oz_report_vector.o \ + umfpack_oz_solve.o umfpack_oz_symbolic.o umfpack_oz_transpose.o \ + umfpack_oz_triplet_to_col.o umfpack_oz_scale.o \ + umfpack_oz_load_numeric.o umfpack_oz_save_numeric.o \ + umfpack_oz_load_symbolic.o umfpack_oz_save_symbolic.o \ + umfpack_o_timer.o umfpack_o_tictoc.o \ + amd_o_aat.o amd_o_1.o amd_o_2.o amd_o_dump.o \ + amd_o_postorder.o amd_o_post_tree.o amd_o_defaults.o amd_o_order.o \ + amd_o_control.o amd_o_info.o amd_o_valid.o + +luflop: luflop.cc + $(MKOCT) luflop.cc -I$(OCT_SPARSE_INC) -o luflop.oct + +#---------------------------------------- +# umfpack library to link with octave +#---------------------------------------- + +octave: umfpack + ld -r -o ../../../$(OCTUMFPACK_LIB) \ + umf_o_analyze.o umf_o_apply_order.o umf_o_colamd.o umf_o_free.o \ + umf_o_fsize.o umf_o_is_permutation.o umf_o_malloc.o \ + umf_o_realloc.o umf_o_report_perm.o umf_o_singletons.o \ + umf_od_lhsolve.o umf_od_uhsolve.o umf_od_triplet_map_nox.o \ + umf_od_triplet_nomap_x.o umf_od_triplet_nomap_nox.o \ + umf_od_triplet_map_x.o umf_od_assemble_fixq.o \ + umf_od_store_lu_drop.o umf_od_assemble.o umf_od_blas3_update.o \ + umf_od_build_tuples.o umf_od_create_element.o umf_od_dump.o \ + umf_od_extend_front.o umf_od_garbage_collection.o \ + umf_od_get_memory.o umf_od_init_front.o umf_od_kernel.o \ + umf_od_kernel_init.o umf_od_kernel_wrapup.o umf_od_local_search.o \ + umf_od_lsolve.o umf_od_ltsolve.o umf_od_mem_alloc_element.o \ + umf_od_mem_alloc_head_block.o umf_od_mem_alloc_tail_block.o \ + umf_od_mem_free_tail_block.o umf_od_mem_init_memoryspace.o \ + umf_od_report_vector.o umf_od_row_search.o umf_od_scale_column.o \ + umf_od_set_stats.o umf_od_solve.o umf_od_symbolic_usage.o \ + umf_od_transpose.o umf_od_tuple_lengths.o umf_od_usolve.o \ + umf_od_utsolve.o umf_od_valid_numeric.o umf_od_valid_symbolic.o \ + umf_od_grow_front.o umf_od_start_front.o umf_od_2by2.o \ + umf_od_store_lu.o umf_od_scale.o umfpack_od_wsolve.o \ + umfpack_od_col_to_triplet.o umfpack_od_defaults.o \ + umfpack_od_free_numeric.o umfpack_od_free_symbolic.o \ + umfpack_od_get_numeric.o umfpack_od_get_lunz.o \ + umfpack_od_get_symbolic.o umfpack_od_numeric.o \ + umfpack_od_qsymbolic.o umfpack_od_report_control.o \ + umfpack_od_report_info.o umfpack_od_report_matrix.o \ + umfpack_od_report_numeric.o umfpack_od_report_perm.o \ + umfpack_od_report_status.o umfpack_od_report_symbolic.o \ + umfpack_od_report_triplet.o umfpack_od_report_vector.o \ + umfpack_od_solve.o umfpack_od_symbolic.o umfpack_od_transpose.o \ + umfpack_od_triplet_to_col.o umfpack_od_scale.o \ + umfpack_od_load_numeric.o umfpack_od_save_numeric.o \ + umfpack_od_load_symbolic.o umfpack_od_save_symbolic.o \ + umf_oz_lhsolve.o umf_oz_uhsolve.o umf_oz_triplet_map_nox.o \ + umf_oz_triplet_nomap_x.o umf_oz_triplet_nomap_nox.o \ + umf_oz_triplet_map_x.o umf_oz_assemble_fixq.o \ + umf_oz_store_lu_drop.o umf_oz_assemble.o umf_oz_blas3_update.o \ + umf_oz_build_tuples.o umf_oz_create_element.o umf_oz_dump.o \ + umf_oz_extend_front.o umf_oz_garbage_collection.o \ + umf_oz_get_memory.o umf_oz_init_front.o umf_oz_kernel.o \ + umf_oz_kernel_init.o umf_oz_kernel_wrapup.o umf_oz_local_search.o \ + umf_oz_lsolve.o umf_oz_ltsolve.o umf_oz_mem_alloc_element.o \ + umf_oz_mem_alloc_head_block.o umf_oz_mem_alloc_tail_block.o \ + umf_oz_mem_free_tail_block.o umf_oz_mem_init_memoryspace.o \ + umf_oz_report_vector.o umf_oz_row_search.o umf_oz_scale_column.o \ + umf_oz_set_stats.o umf_oz_solve.o umf_oz_symbolic_usage.o \ + umf_oz_transpose.o umf_oz_tuple_lengths.o umf_oz_usolve.o \ + umf_oz_utsolve.o umf_oz_valid_numeric.o umf_oz_valid_symbolic.o \ + umf_oz_grow_front.o umf_oz_start_front.o umf_oz_2by2.o \ + umf_oz_store_lu.o umf_oz_scale.o umfpack_oz_wsolve.o \ + umfpack_oz_col_to_triplet.o umfpack_oz_defaults.o \ + umfpack_oz_free_numeric.o umfpack_oz_free_symbolic.o \ + umfpack_oz_get_numeric.o umfpack_oz_get_lunz.o \ + umfpack_oz_get_symbolic.o umfpack_oz_numeric.o \ + umfpack_oz_qsymbolic.o umfpack_oz_report_control.o \ + umfpack_oz_report_info.o umfpack_oz_report_matrix.o \ + umfpack_oz_report_numeric.o umfpack_oz_report_perm.o \ + umfpack_oz_report_status.o umfpack_oz_report_symbolic.o \ + umfpack_oz_report_triplet.o umfpack_oz_report_vector.o \ + umfpack_oz_solve.o umfpack_oz_symbolic.o umfpack_oz_transpose.o \ + umfpack_oz_triplet_to_col.o umfpack_oz_scale.o \ + umfpack_oz_load_numeric.o umfpack_oz_save_numeric.o \ + umfpack_oz_load_symbolic.o umfpack_oz_save_symbolic.o \ + umfpack_o_timer.o umfpack_o_tictoc.o \ + amd_o_aat.o amd_o_1.o amd_o_2.o amd_o_dump.o \ + amd_o_postorder.o amd_o_post_tree.o amd_o_defaults.o amd_o_order.o \ + amd_o_control.o amd_o_info.o amd_o_valid.o + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) *.oct* *.dll diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/lu_normest.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/lu_normest.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/lu_normest.m @@ -0,0 +1,106 @@ +function rho = lu_normest (A, L, U) +% LU_NORMEST: estimate the 1-norm of A-L*U without computing L*U +% +% Usage: +% +% rho = lu_normest (A, L, U) +% +% which estimates the computation of the 1-norm: +% +% rho = norm (A-L*U, 1) +% +% Authors: William W. Hager, Math Dept., Univ. of Florida +% Timothy A. Davis, CISE Dept., Univ. of Florida +% Gainesville, FL, 32611, USA. +% based on normest1, contributed on November, 1997 +% +% This code can be quite easily adapted to estimate the 1-norm of any +% matrix E, where E itself is dense or not explicitly represented, but the +% computation of E (and E') times a vector is easy. In this case, our matrix +% of interest is: +% +% E = A-L*U +% +% That is, L*U is the LU factorization of A, where A, L and U +% are sparse. This code works for dense matrices A and L too, +% but it would not be needed in that case, since E is easy to compute +% explicitly. For sparse A, L, and U, computing E explicitly would be quite +% expensive, and thus normest (A-L*U) would be prohibitive. +% +% For a detailed description, see Davis, T. A. and Hager, W. W., +% Modifying a sparse Cholesky factorization, SIAM J. Matrix Analysis and +% Applications, 1999, vol. 20, no. 3, 606-627. + +% The three places that the matrix-vector multiply E*x is used are highlighted. +% Note that E is never formed explicity. + +[m n] = size (A) ; + +if (m ~= n) + % pad A, L, and U with zeros so that they are all square + if (m < n) + U = [ U ; (sparse (n-m,n)) ] ; + L = [ L , (sparse (m,n-m)) ; (sparse (n-m,n)) ] ; + A = [ A ; (sparse (n-m,n)) ] ; + else + U = [ U , (sparse (n,m-n)) ; (sparse (m-n,m)) ] ; + L = [ L , (sparse (m,m-n)) ] ; + A = [ A , (sparse (m,m-n)) ] ; + end +end + +[m n] = size (A) ; + +notvisited = ones (m, 1) ; % nonvisited(j) is zero if j is visited, 1 otherwise +rho = 0 ; % the global rho + +At = A' ; +Lt = L' ; + +for trial = 1:3 % { + + x = notvisited ./ sum (notvisited) ; + rho1 = 0 ; % the current rho for this trial + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Ex1 = (A*x) - L*(U*x) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + rho2 = norm (Ex1, 1) ; + + while rho2 > rho1 % { + + rho1 = rho2 ; + y = 2*(Ex1 >= 0) - 1 ; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE z = E'*y EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + z = (A'*y) - U'*(L'*y) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + [zj, j] = max (abs (z .* notvisited)) ; + j = j (1) ; + if (abs (z (j)) > z'*x) % { + x = zeros (m, 1) ; + x (j) = 1 ; + notvisited (j) = 0 ; + else % } { + break ; + end % } + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%% COMPUTE Ex1 = E*x EFFICIENTLY: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Ex1 = (A*x) - L*(U*x) ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + rho2 = norm (Ex1, 1) ; + + end % } + + rho = max (rho, rho1) ; + +end % } diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/luflop.cc b/liboctave/UMFPACK/UMFPACK/OCTAVE/luflop.cc new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/luflop.cc @@ -0,0 +1,223 @@ +/* + +Copyright (C) 2004 David Bateman + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +In addition to the terms of the GPL, you are permitted to link +this program with any Open Source program, as defined by the +Open Source Initiative (www.opensource.org) + +*/ + +/* + +This is the Octave interface to the UMFPACK code, which bore the following +copyright + + UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. + Davis. All Rights Reserved. See ../README for License. + email: davis@cise.ufl.edu CISE Department, Univ. of Florida. + web: http://www.cise.ufl.edu/research/sparse/umfpack + +*/ + + +#include +#include + +#include +#include +#include +#include +#include + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +DEFUN_DLD (luflop, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{f} =} luflup (@var{l}, @var{u})\n\ +\n\ +Given an LU factorization, compute how many flops took to compute it. This\n\ +is the same as (assuming U has a zero-free diagonal):\n\ +\n\ +@example\n\ +@group\n\ + Lnz = full (sum (spones (L))) - 1 ;\n\ + Unz = full (sum (spones (U')))' - 1 ;\n\ + f = 2*Lnz*Unz + sum (Lnz) ;\n\ +@end group\n\ +@end example\n\ +\n\ +except that no extra workspace is allocated for spones (L) and spones (U).\n\ +L and U must be sparse.\n\ +\n\ +Note: the above expression has a subtle undercount when exact numerical\n\ +cancelation occurs. Try [L,U,P] = lu (sparse (ones (10))) and then\n\ +luflop (L,U).\n\ +@end deftypefn") +{ + int nargin = args.length (); + octave_value retval; + + // These are here only so that the C++ destructors don't prematurally + // remove the underlying data we are interested in + SparseMatrix Lmatrix, Umatrix; + SparseComplexMatrix CLmatrix, CUmatrix; + int *Lp, *Li, *Up, *Ui; + int Lm, Ln, Um, Un; + + if (nargin != 2) + { + usage ("f = luflop (L, U)"); + return retval; + } + + if (args(0).class_name () == "sparse") + { + if (args(0).is_complex_type ()) + { + CLmatrix = + (((const octave_sparse_complex_matrix&) args(0).get_rep ()) + .sparse_complex_matrix_value ()); + Lp = CLmatrix.cidx (); + Li = CLmatrix.ridx (); + Lm = CLmatrix.rows (); + Ln = CLmatrix.cols (); + } + else + { + Lmatrix = (((const octave_sparse_matrix&) args(0).get_rep ()) + .sparse_matrix_value ()); + Lp = Lmatrix.cidx (); + Li = Lmatrix.ridx (); + Lm = Lmatrix.rows (); + Ln = Lmatrix.cols (); + } + } + else + { + if (args(0).is_complex_type ()) + { + CLmatrix = SparseComplexMatrix (args(0).complex_matrix_value ()); + Lp = CLmatrix.cidx (); + Li = CLmatrix.ridx (); + Lm = CLmatrix.rows (); + Ln = CLmatrix.cols (); + } + else + { + Lmatrix = SparseMatrix (args(0).matrix_value ()); + Lp = Lmatrix.cidx (); + Li = Lmatrix.ridx (); + Lm = Lmatrix.rows (); + Ln = Lmatrix.cols (); + } + } + + + if (args(0).class_name () == "sparse") + { + if (args(1).is_complex_type ()) + { + CUmatrix = + (((const octave_sparse_complex_matrix&) args(1).get_rep ()) + .sparse_complex_matrix_value ()); + Up = CUmatrix.cidx (); + Ui = CUmatrix.ridx (); + Um = CUmatrix.rows (); + Un = CUmatrix.cols (); + } + else + { + Umatrix = + (((const octave_sparse_matrix&) args(1).get_rep ()) + .sparse_matrix_value ()); + Up = Umatrix.cidx (); + Ui = Umatrix.ridx (); + Um = Umatrix.rows (); + Un = Umatrix.cols (); + } + } + else + { + if (args(1).is_complex_type ()) + { + CUmatrix = SparseComplexMatrix (args(1).complex_matrix_value ()); + Up = CUmatrix.cidx (); + Ui = CUmatrix.ridx (); + Um = CUmatrix.rows (); + Un = CUmatrix.cols (); + } + else + { + Umatrix = SparseMatrix (args(1).matrix_value ()); + Up = Umatrix.cidx (); + Ui = Umatrix.ridx (); + Um = Umatrix.rows (); + Un = Umatrix.cols (); + } + } + + + if (error_state) + return retval; + + + int n = Lm; + + if (n != Ln || n != Um || n != Un) + error ("luflop: L and U must be square"); + else + { + + OCTAVE_LOCAL_BUFFER (int, Unz, n); + + // count the nonzeros in each row of U + for (int row = 0 ; row < n ; row++) + Unz [row] = 0 ; + + for (int col = 0 ; col < n ; col++) + { + for (int p = Up [col] ; p < Up [col+1] ; p++) + { + int row = Ui [p] ; + Unz [row]++ ; + } + } + + // count the flops + double flop_count = 0.0 ; + for (int k = 0 ; k < n ; k++) + { + /* off-diagonal nonzeros in column k of L: */ + int Lnz_k = Lp [k+1] - Lp [k] - 1 ; + int Unz_k = Unz [k] - 1 ; + flop_count += (2 * Lnz_k * Unz_k) + Lnz_k ; + } + + // return the result + retval = flop_count; + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack.cc b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack.cc new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack.cc @@ -0,0 +1,1399 @@ +/* + +Copyright (C) 2004 David Bateman + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +In addition to the terms of the GPL, you are permitted to link +this program with any Open Source program, as defined by the +Open Source Initiative (www.opensource.org) + +*/ + +/* + +This is the Octave interface to the UMFPACK code, which bore the following +copyright + + UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. + Davis. All Rights Reserved. See ../README for License. + email: davis@cise.ufl.edu CISE Department, Univ. of Florida. + web: http://www.cise.ufl.edu/research/sparse/umfpack + +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// External UMFPACK functions in C +extern "C" { +#include "umfpack.h" +} + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +// Return an error message +static +void umfpack_error (const char *s, int A_is_complex, int nargout, + octave_value_list retval, NDArray Control, + NDArray Info, int status, int do_info) +{ + if (A_is_complex) + { + umfpack_zi_report_status (Control.fortran_vec (), status) ; + umfpack_zi_report_info (Control.fortran_vec (), Info.fortran_vec ()) ; + } + else + { + umfpack_di_report_status (Control.fortran_vec (), status) ; + umfpack_di_report_info (Control.fortran_vec (), Info.fortran_vec ()) ; + } + if (do_info > 0) + // return Info + retval (do_info) = octave_value (Info); + + error (s); +} + +DEFUN_DLD (umfpack, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, '\\', @var{b})\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, '\\', @var{b}, @var{Control})\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, '\\', @var{b}, @var{Control})\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, '\\', b)\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', A) ;\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Qinit}) ;\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{Info}] =} umfpack (@var{b}, '/', @var{a}, @var{Qinit}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}, @var{Info}] =} umfpack (@var{a}, @var{Qinit}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Qinit}) ;\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{p}, @var{q}] =} umfpack (@var{a}, @var{Qinit}, @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, 'symbolic') ;\n\ +@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, 'symbolic', @var{Control}) ;\n\ +@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, @var{Qinit}, 'symbolic') ;\n\ +@deftypefnx {Loadable Function} {[P1, Q1, Fr, Ch, Info] =} umfpack (@var{a}, @var{Qinit}, 'symbolic', @var{Control});\n\ +@deftypefnx {Loadable Function} {@var{Control} =} umfpack ;\n\ +\n\ +UMFPACK v4.3 is a Octave oct-file for solving sparse linear systems.\n\ +\n\ +@iftex\n\ +@tex\n\ +\\vskip 2ex\n\ +\\hfil\\vbox{\n\ +\\offinterlineskip\n\ +\\tabskip=0pt\n\ +\\halign{\n\ +\\vrule height1.75ex depth1.25ex width 0.6pt #\\tabskip=1em &\n\ +\\hfil #\\hfil &\\vrule # & \n\ +\\hfil #\\hfil &\\vrule # width 0.6pt \\tabskip=0pt\\cr\n\ +\\noalign{\\hrule height 0.6pt}\n\ +& UMFPACK v4.3 && OCTAVE approximate equivalent &\\cr\n\ +\\noalign{\\hrule} \n\ +& x = umfpack (A, '\\', b) ; && x = A \\ b &\\cr\n\ +& && &\\cr\n\ +&x = umfpack (b, '/', A) ; && x = b / A &\\cr\n\ +& && &\\cr\n\ +&[L,U,P,Q] = umfpack (A) ; && [m,n] = size (A) ; &\\cr\n\ +& && I = speye (n) ; &\\cr\n\ +& && Q = I (:, colamd (A)) ; &\\cr\n\ +& && [L,U,P] = lu (A*Q) ; &\\cr\n\ +& && &\\cr\n\ +&[L,U,P,Q,R] = umfpack (A) ; && [m,n] = size (A) ; &\\cr\n\ +& && I = speye (n) ; &\\cr\n\ +& && Q = I (:, colamd (A)) ; &\\cr\n\ +& && r = full (sum (abs (A), 2)) ; &\\cr\n\ +& && r (find (r == 0)) = 1 ; &\\cr\n\ +& && R = spdiags (r, 0, m, m) ; &\\cr\n\ +& && [L,U,P] = lu ((R\\A)*Q) ; &\\cr\n\ +& && &\\cr\n\ +&[P,Q,F,C] = umfpack (A, 'symbolic')&& [m,n] = size (A) ; &\\cr\n\ +& && I = speye (n) ; &\\cr\n\ +& && Q = I (:, colamd (A)) ; &\\cr\n\ +& && [count,h,parent,post] = ... &\\cr\n\ +& && symbfact (A*Q, 'col') ; &\\cr\n\ +\\noalign{\\hrule height 0.6pt}\n\ +}}\\hfil\n\ +\\vskip 1ex\n\ +@end tex\n\ +@end iftex\n\ +@ifinfo\n\ +@multitable @columnfractions 0.43 .02 .43\n\ +@item UMFPACK v4.3: @tab | \n\ +@tab OCTAVE approx. equivalent\n\ +@item ------------------------------- @tab | \n\ +@tab --------------------------------\n\ +@item x = umfpack (A, '\\', b) ; @tab | \n\ +@tab x = A \\ b\n\ +@item @tab | \n\ +@tab\n\ +@item x = umfpack (b, '/', A) ; @tab | \n\ +@tab x = b / A\n\ +@item @tab | \n\ +@tab\n\ +@item [L,U,P,Q] = umfpack (A) ; @tab | \n\ +@tab [m,n] = size (A) ;\n\ +@item @tab | \n\ +@tab I = speye (n) ;\n\ +@item @tab | \n\ +@tab Q = I (:, colamd (A)) ;\n\ +@item @tab | \n\ +@tab [L,U,P] = lu (A*Q) ;\n\ +@item @tab | \n\ +@tab\n\ +@item [L,U,P,Q,R] = umfpack (A) ; @tab | \n\ +@tab [m,n] = size (A) ;\n\ +@item @tab | \n\ +@tab I = speye (n) ;\n\ +@item @tab | \n\ +@tab Q = I (:, colamd (A)) ;\n\ +@item @tab | \n\ +@tab r = full (sum (abs (A), 2)) ;\n\ +@item @tab | \n\ +@tab r (find (r == 0)) = 1 ;\n\ +@item @tab | \n\ +@tab R = spdiags (r, 0, m, m) ;\n\ +@item @tab | \n\ +@tab [L,U,P] = lu ((R\\A)*Q) ;\n\ +@item @tab | \n\ +@tab\n\ +@item [P,Q,F,C] = umfpack (A, 'symbolic') @tab | \n\ +@tab [m,n] = size (A) ; \n\ +@item @tab | \n\ +@tab I = speye (n) ;\n\ +@item @tab | \n\ +@tab Q = I (:, colamd (A)) ;\n\ +@item @tab | \n\ +@tab [count,h,parent,post] = ...\n\ +@item @tab | \n\ +@tab symbfact (A*Q, 'col') ;\n\ +@end multitable\n\ +@end ifinfo\n\ +\n\ +A must be sparse. It can be complex, singular, and/or rectangular.\n\ +A must be square for '/' or '\\'. b must be a full real or complex\n\ +vector. For @code{[@var{l}, @var{u}, @var{p}, @var{q}, @var{r}] =\n\ +umfpack (@var{a})}, the factorization is @code{@var{l} * @var{u} =\n\ +@var{p} * (@var{r} \\ @var{a}) * @var{q}}. If @var{a} has a mostly\n\ +symmetric nonzero pattern, then replace @dfn{colamd} with @dfn{amd}\n\ +in the OCTAVE-equivalent column in the table above.\n\ +\n\ +Factor or solve a sparse linear system, returning either the solution\n\ +@var{x} to @code{@var{A} * @var{x} = @var{b}} or @code{@var{A}' * @var{x}'\n\ += @var{b}'}, the factorization LU=PAQ, or LU=P(R\\A)Q. A must be sparse.\n\ +For the solve, A must be square and b must be a dense n-by-1 vector. For LU\n\ +factorization, A can be rectangular. In both cases, A and/or b can be real\n\ +or complex.\n\ +\n\ +UMFPACK analyzes the matrix and selects one of three strategies to factorize\n\ +the matrix. It first finds a set of k initial pivot entries of zero\n\ +Markowitz cost. This forms the first k rows and columns of L and U. The\n\ +remaining submatrix S is then analyzed, based on the symmetry of the nonzero\n\ +pattern of the submatrix and the values on the diagaonal. The strategies\n\ +include:\n\ +\n\ +@table @asis\n\ +@item unsymmetric\n\ +Use a COLAMD pre-ordering, a column elimination tree\n\ +post-ordering, refine the column ordering during factorization,\n\ +and make no effort at selecting pivots on the diagonal.\n\ +@item 2-by-2\n\ +Like the symmetric strategy (see below), except that local\n\ +row permutations are first made to attempt to place large entries\n\ +on the diagonal.\n\ +@item symmetric\n\ +Use an AMD pre-ordering on the matrix @code{@var{s} + @var{s}'}, an\n\ +elimination tree post-ordering, do not refine the column ordering during\n\ +factorization, and attempt to select pivots on the diagonal.\n\ +@end table\n\ +\n\ +Each of the following uses of umfpack (except for 'Control = umfpack') is\n\ +stand-alone. That is, no call to umfpack is required for any subsequent\n\ +call. In each usage, the Info output argument is optional.\n\ +\n\ +Usage:\n\ +\n\ +[x, Info] = umfpack (A, '\\', b) ;\n\ +[x, Info] = umfpack (A, '\\', b, Control) ;\n\ +[x, Info] = umfpack (A, Qinit, '\\', b, Control) ;\n\ +[x, Info] = umfpack (A, Qinit, '\\', b) ;\n\ +\n\ + Solves Ax=b (similar to x = A\\b in OCTAVE).\n\ +\n\ +[x, Info] = umfpack (b, '/', A) ;\n\ +[x, Info] = umfpack (b, '/', A, Control) ;\n\ +[x, Info] = umfpack (b, '/', A, Qinit) ;\n\ +[x, Info] = umfpack (b, '/', A, Qinit, Control) ;\n\ +\n\ + Solves A'x'=b' (similar to x = b/A in OCTAVE).\n\ +\n\ +[L, U, P, Q, R, Info] = umfpack (A) ;\n\ +[L, U, P, Q, R, Info] = umfpack (A, Control) ;\n\ +[L, U, P, Q, R, Info] = umfpack (A, Qinit) ;\n\ +[L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ;\n\ +\n\ + Returns the LU factorization of A. P and Q are returned as permutation\n\ + matrices. R is a diagonal sparse matrix of scale factors for the rows\n\ + of A, L is lower triangular, and U is upper triangular. The\n\ + factorization is L*U = P*(R\\A)*Q. You can turn off scaling by setting\n\ + Control (17) to zero (in which case R = speye (m)), or by using the\n\ + following syntaxes (in which case Control (17) is ignored):\n\ +\n\ +[L, U, P, Q] = umfpack (A) ;\n\ +[L, U, P, Q] = umfpack (A, Control) ;\n\ +[L, U, P, Q] = umfpack (A, Qinit) ;\n\ +[L, U, P, Q] = umfpack (A, Qinit, Control) ;\n\ +\n\ + Same as above, except that no row scaling is performed. The Info array\n\ + is not returned, either.\n\ +\n\ +[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ;\n\ +[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic', Control) ;\n\ +[P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic') ;\n\ +[P1, Q1, Fr, Ch, Info] = umfpack (A, Qinit, 'symbolic', Control);\n\ +\n\ + Performs only the fill-reducing column pre-ordering (including the\n\ + elimination tree post-ordering) and symbolic factorization. Q1 is the\n\ + initial column permutation (either from colamd, amd, or the input\n\ + ordering Qinit), possibly followed by a column elimination tree post-\n\ + ordering or a symmetric elimination tree post-ordering, depending on\n\ + the strategy used.\n\ +\n\ + For the unsymmetric strategy, P1 is the row ordering induced by Q1\n\ + (row-merge order). For the 2-by-2 strategy, P1 is the row ordering that\n\ + places large entries on the diagonal of P1*A*Q1. For the symmetric\n\ + strategy, P1 = Q1.\n\ +\n\ + Fr is a (nfr+1)-by-4 array containing information about each frontal\n\ + matrix, where nfr <= n is the number of frontal matrices. Fr (:,1) is\n\ + the number of pivot columns in each front, and Fr (:,2) is the parent\n\ + of each front in the supercolumn elimination tree. Fr (k,2) is zero if\n\ + k is a root. The first Fr (1,1) columns of P1*A*Q1 are the pivot\n\ + columns for the first front, the next Fr (2,1) columns of P1*A*Q1\n\ + are the pivot columns for the second front, and so on.\n\ +\n\ + For the unsymmetric strategy, Fr (:,3) is the row index of the first\n\ + row in P1*A*Q1 whose leftmost nonzero entry is in a pivot column for\n\ + the kth front. Fr (:,4) is the leftmost descendent of the kth front.\n\ + Rows in the range Fr (Fr (k,4),3) to Fr (k+1,3)-1 form the entire set\n\ + of candidate pivot rows for the kth front (some of these will typically\n\ + have been selected as pivot rows of fronts Fr (k,3) to k-1, before the\n\ + factorization reaches the kth front. If front k is a leaf node, then\n\ + Fr (k,4) is k.\n\ +\n\ + Ch is a (nchains+1)-by-3 array containing information about each\n\ + 'chain' (unifrontal sequence) of frontal matrices, and where\n\ + nchains <= nfr is the number of chains. The ith chain consists of\n\ + frontal matrices. Chain (i,1) to Chain (i+1,1)-1, and the largest\n\ + front in chain i is Chain (i,2)-by-Chain (i,3).\n\ +\n\ + This use of umfpack is not required to factor or solve a linear system\n\ + in OCTAVE. It analyzes the matrix A and provides information only.\n\ + The OCTAVE statement @code{treeplot (Fr (:,2)')} plots the column\n\ + elimination tree.\n\ +\n\ +Control = umfpack ;\n\ +\n\ + Returns a 20-by-1 vector of default parameter settings for umfpack.\n\ +\n\ +umfpack_report (Control, Info) ;\n\ +\n\ + Prints the current Control settings, and Info\n\ +\n\ +If present, Qinit is a user-supplied 1-by-n permutation vector. It is an\n\ +initial fill-reducing column pre-ordering for A; if not present, then colamd\n\ +or amd are used instead. If present, Control is a user-supplied 20-by-1\n\ +array. Control and Info are optional; if Control is not present, defaults\n\ +are used. If a Control entry is NaN, then the default is used for that entry.\n\ +\n\ +UMFPACK Version 4.3 (Jan. 16, 2004), Copyright @copyright{} 2004 by\n\ +Timothy A. Davis. All Rights Reserved.\n\ +\n\ +UMFPACK License:\n\ +\n\ +@example\n\ +Your use or distribution of UMFPACK or any modified version of\n\ +UMFPACK implies that you agree to this License.\n\ +\n\ +THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY\n\ +EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.\n\ +\n\ +Permission is hereby granted to use or copy this program, provided\n\ +that the Copyright, this License, and the Availability of the original\n\ +version is retained on all copies. User documentation of any code that\n\ +uses UMFPACK or any modified version of UMFPACK code must cite the\n\ +Copyright, this License, the Availability note, and 'Used by permission.'\n\ +Permission to modify the code and to distribute modified code is granted,\n\ +provided the Copyright, this License, and the Availability note are\n\ +retained, and a notice that the code was modified is included. This\n\ +software was developed with support from the National Science Foundation,\n\ +and is provided to you free of charge.\n\ +@end example\n\ +\n\ +Availability: http://www.cise.ufl.edu/research/sparse/umfpack\n\ +@end deftypefn\n\ +@seealso{lu_normtest, colamd, amd, umfpack_solve}") +{ + octave_value_list retval; + int nargin = args.length (); + int op = 0; + std::string operation; + bool do_solve = false; + int do_info = 0; + + ColumnVector User_Qinit; + SparseComplexMatrix CAmatrix; + ComplexMatrix CBmatrix; + SparseMatrix Amatrix; + Matrix Bmatrix; + NDArray User_Control_matrix; + + bool A_is_complex = false; + bool B_is_complex = false; + bool X_is_complex = false; + bool transpose = false; + bool have_User_Qinit = false; + bool have_User_Control_matrix = false; + bool do_numeric = true; + bool no_scale = false; + + // find the operator + for (int i = 0 ; i < nargin ; i++) + { + if (args(i).is_string ()) + { + op = i; + break; + } + } + + if (op > 0) + { + std::string op_type = args (op).string_value (); + + if (op_type == "\\") + { + + // matrix left divide, x = A\b + + // [x, Info] = umfpack (A, '\', b) ; + // [x, Info] = umfpack (A, '\', b, Control) ; + // [x, Info] = umfpack (A, Qinit, '\', b, Control) ; + // [x, Info] = umfpack (A, Qinit, '\', b) ; + + do_solve = true; + operation = "x = A\\b"; + + if (args(0).class_name () != "sparse") + { + error ("umfpack: input matrix A must be sparse"); + return retval; + } + + if (args(0).is_complex_type ()) + { + CAmatrix = args(0).sparse_complex_matrix_value (); + A_is_complex = true; + } + else + Amatrix = args(0).sparse_matrix_value (); + + + if (args(op+1).is_complex_type ()) + { + CBmatrix = args(op+1).complex_matrix_value (); + B_is_complex = true; + } + else + Bmatrix = args(op+1).matrix_value (); + + if (nargout == 2) + do_info = 1; + + if (op == 2) + { + User_Qinit = args(1).column_vector_value (); + have_User_Qinit = true; + } + + if ((op == 1 && nargin == 4) || (op == 2 && nargin == 5)) + { + User_Control_matrix = args(nargin-1).array_value (); + have_User_Control_matrix = true; + } + + if (error_state) + { + error ("umfpack: incorrect argument type"); + return retval; + } + + if (nargin < 3 || nargin > 5 || nargout > 2) + { + error ("umfpack: wrong number of arguments"); + return retval; + } + + } + else if (op_type == "/") + { + // matrix right divide, x = b/A + + // [x, Info] = umfpack (b, '/', A) ; + // [x, Info] = umfpack (b, '/', A, Control) ; + // [x, Info] = umfpack (b, '/', A, Qinit) ; + // [x, Info] = umfpack (b, '/', A, Qinit, Control) ; + + do_solve = true; + operation = "x = b/A" ; + + transpose = true; + + if (args(2).class_name () != "sparse") + { + error ("umfpack: input matrix A must be sparse"); + return retval; + } + + if (args(2).is_complex_type ()) + { + CAmatrix = args(2).sparse_complex_matrix_value (); + A_is_complex = true; + } + else + Amatrix = args(2).sparse_matrix_value (); + + if (args(0).is_complex_type ()) + { + CBmatrix = args(0).complex_matrix_value (); + B_is_complex = true; + } + else + Bmatrix = args(0).matrix_value (); + + if (nargout == 2) + do_info = 1; + + if (nargin == 5) + { + User_Qinit = args(3).column_vector_value (); + User_Control_matrix = args(4).array_value (); + have_User_Qinit = true; + have_User_Control_matrix = true; + } + else if (nargin == 4) + { + User_Control_matrix = args(3).array_value (); + + if (User_Control_matrix.rows () == 1) + { + User_Qinit = args(3).column_vector_value (); + have_User_Qinit = true; + } + else + have_User_Control_matrix = true; + } + else if (nargin < 3 || nargin > 5 || nargout > 2) + { + error ("umfpack: wrong number of arguments"); + return retval; + } + + if (error_state) + { + error ("umfpack: incorrect argument type"); + return retval; + } + } + else if (op_type == "symbolic") + { + // symbolic factorization only + + // [P Q Fr Ch Info] = umfpack (A, 'symbolic') ; + // [P Q Fr Ch Info] = umfpack (A, 'symbolic', Control) ; + // [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic') ; + // [P Q Fr Ch Info] = umfpack (A, Qinit, 'symbolic', Control) ; + + operation = "symbolic factorization"; + do_numeric = false; + + if (args(0).class_name () != "sparse") + { + error ("umfpack: input matrix A must be sparse"); + return retval; + } + + if (args(0).is_complex_type ()) + { + CAmatrix = args(0).sparse_complex_matrix_value (); + A_is_complex = true; + } + else + Amatrix = args(0).sparse_matrix_value (); + + if (nargout == 5) + do_info = 4 ; + + if (op == 2) + { + User_Qinit = args(1).column_vector_value (); + have_User_Qinit = true; + } + if ((op == 1 && nargin == 3) || (op == 2 && nargin == 4)) + { + User_Control_matrix = args(nargin-1).array_value (); + have_User_Control_matrix = true; + } + + if (error_state) + { + error ("umfpack: incorrect argument type"); + return retval; + } + + if (nargin < 2 || nargin > 4 || nargout > 5 || nargout < 4) + { + error ("umfpack: wrong number of arguments") ; + return retval; + } + } + else + { + error ("operator must be '/', '\\', or 'symbolic'") ; + return retval; + } + } + else if (nargin > 0) + { + // LU factorization + + // with scaling: + // [L, U, P, Q, R, Info] = umfpack (A) ; + // [L, U, P, Q, R, Info] = umfpack (A, Qinit) ; + // + // scaling determined by Control settings: + // [L, U, P, Q, R, Info] = umfpack (A, Control) ; + // [L, U, P, Q, R, Info] = umfpack (A, Qinit, Control) ; + // + // with no scaling: + // [L, U, P, Q] = umfpack (A) ; + // [L, U, P, Q] = umfpack (A, Control) ; + // [L, U, P, Q] = umfpack (A, Qinit) ; + // [L, U, P, Q] = umfpack (A, Qinit, Control) ; + + operation = "numeric factorization" ; + + if (args(0).is_complex_type ()) + { + CAmatrix = args(0).sparse_complex_matrix_value (); + A_is_complex = true; + } + else + Amatrix = args(0).sparse_matrix_value (); + + no_scale = nargout <= 4 ; + + if (nargout == 6) + do_info = 5 ; + + if (nargin == 3) + { + User_Qinit = args(1).column_vector_value (); + User_Control_matrix = args(2).array_value (); + have_User_Qinit = true; + have_User_Control_matrix = true; + } + else if (nargin == 2) + { + User_Control_matrix = args(1).array_value (); + + if (User_Control_matrix.rows () == 1) + { + User_Qinit = args(1).column_vector_value (); + have_User_Qinit = true; + } + else + have_User_Control_matrix = true; + } + else if (nargin > 3 || nargout > 6 || nargout < 4) + { + error ("umfpack: wrong number of arguments") ; + return retval; + } + } + else + { + // return default control settings + + // Control = umfpack ; + // umfpack ; + + if (nargout > 1) + { + error ("umfpack: wrong number of arguments") ; + return retval; + } + + NDArray user_control (dim_vector (UMFPACK_CONTROL, 1)); + double *user_control_ptr = user_control.fortran_vec (); + umfpack_di_defaults (user_control_ptr); + retval(0) = user_control; + return retval; + } + + // check inputs + + int n_row = Amatrix.rows (); + int n_col = Amatrix.cols (); + int nn = MAX (n_row, n_col) ; + int n_inner = MIN (n_row, n_col) ; + if (do_solve && n_row != n_col) + { + error ("umfpack: input matrix A must square for '\\' or '/'") ; + return retval; + } + if (n_row == 0 || n_col == 0) + { + error ("umfpack: input matrix A cannot have zero rows or zero columns") ; + return retval; + } + + /* The real/complex status of A determines which version to use, */ + /* (umfpack_di_* or umfpack_zi_*). */ + const int *Ap; + const int *Ai; + const double *Ax; + const double *Bx; + + if (A_is_complex) + { + Ap = CAmatrix.cidx (); + Ai = CAmatrix.ridx (); + Ax = X_CAST (const double *, CAmatrix.data ()); + } + else + { + Ap = Amatrix.cidx (); + Ai = Amatrix.ridx (); + Ax = Amatrix.data (); + } + + if (B_is_complex) + Bx = X_CAST (const double *, CBmatrix.fortran_vec ()); + else + Bx = Bmatrix.fortran_vec (); + + if (do_solve) + { + int b_row = Bmatrix.rows (); + int b_col = Bmatrix.cols (); + + if (!((transpose && b_row == 1 && b_col == nn) || + (!transpose && b_row == nn && b_col == 1))) + { + error ("umfpack: b has the wrong dimensions") ; + return retval; + } + + X_is_complex = A_is_complex || B_is_complex ; + } + + // set the Control parameters + NDArray Control (dim_vector (UMFPACK_CONTROL, 1)); + double *Control_ptr = Control.fortran_vec (); + if (A_is_complex) + umfpack_zi_defaults (Control_ptr) ; + else + umfpack_di_defaults (Control_ptr) ; + + if (have_User_Control_matrix) + { + int size = MIN (UMFPACK_CONTROL, User_Control_matrix.length ()); + for (int i = 0 ; i < size ; i++) + Control (i) = User_Control_matrix (i) ; + } + + if (no_scale) + { + // turn off scaling for [L, U, P, Q] = umfpack (A) ; + // ignoring the input value of Control (24) for the usage + // [L, U, P, Q] = umfpack (A, Control) ; + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE ; + } + + int print_level; + if (xisnan (Control (UMFPACK_PRL))) + print_level = UMFPACK_DEFAULT_PRL ; + else + print_level = int (Control (UMFPACK_PRL)) ; + + Control (UMFPACK_PRL) = print_level ; + + // check Qinit, if present + int *Qinit = NULL; + if (have_User_Qinit) + { + if(User_Qinit.rows () != 1 || User_Qinit.cols () != n_col) + { + error ("umfpack: Qinit must be 1-by-n_col") ; + return retval; + } + + Qinit = new int [n_col]; + for (int i = 0; i < n_col; i++) + Qinit[i] = static_cast (User_Qinit (i)); + } + + // report the inputs A and Qinit + + if (print_level >= 2) + // print the operation + octave_stdout << "\numfpack: " << operation; + + if (A_is_complex) + { + umfpack_zi_report_control (Control_ptr) ; + + if (print_level >= 3) + octave_stdout << "\nA: " ; + + umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, NULL, + 1, Control_ptr) ; + if (have_User_Qinit) + { + if (print_level >= 3) + octave_stdout << "\nQinit: " ; + + umfpack_zi_report_perm (n_col, Qinit, Control_ptr) ; + } + } + else + { + umfpack_di_report_control (Control_ptr) ; + + if (print_level >= 3) + octave_stdout << "\nA: " ; + + umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, + 1, Control_ptr) ; + if (have_User_Qinit) + { + if (print_level >= 3) + octave_stdout << "\nQinit: " ; + + umfpack_di_report_perm (n_col, Qinit, Control_ptr) ; + } + } + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + // create the array transpose for x = b/A + if (transpose) + if (A_is_complex) + { + CAmatrix = CAmatrix.transpose (); + Ap = Amatrix.cidx (); + Ai = Amatrix.ridx (); + Ax = X_CAST (const double *, CAmatrix.data ()); + } + else + { + Amatrix = Amatrix.transpose (); + Ap = Amatrix.cidx (); + Ai = Amatrix.ridx (); + Ax = Amatrix.data (); + } +#endif + + // perform the symbolic factorization + + NDArray InfoOut (dim_vector (1, UMFPACK_INFO)); + double * Info = InfoOut.fortran_vec (); + void *Symbolic; + int status, status2; + if (A_is_complex) + status = umfpack_zi_qsymbolic (n_row, n_col, Ap, Ai, Ax, NULL, + Qinit, &Symbolic, Control_ptr, + Info); + else + status = umfpack_di_qsymbolic (n_row, n_col, Ap, Ai, Ax, + Qinit, &Symbolic, Control_ptr, + Info); + + if (status < 0) + { + umfpack_error ("symbolic factorization failed", A_is_complex, + nargout, retval, Control, InfoOut, status, do_info) ; + return retval; + } + + if (have_User_Qinit) + delete [] Qinit; + + // report the Symbolic object + + if (A_is_complex) + umfpack_zi_report_symbolic (Symbolic, Control_ptr) ; + else + umfpack_di_report_symbolic (Symbolic, Control_ptr) ; + + // perform numeric factorization, or just return symbolic factorization + + if (do_numeric) + { + // perform the numeric factorization + void *Numeric; + + if (A_is_complex) + status = umfpack_zi_numeric (Ap, Ai, Ax, NULL, Symbolic, &Numeric, + Control_ptr, Info) ; + else + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + Control_ptr, Info) ; + + // free the symbolic factorization + if (A_is_complex) + umfpack_zi_free_symbolic (&Symbolic) ; + else + umfpack_di_free_symbolic (&Symbolic) ; + + // report the Numeric object + if (status < 0) + { + umfpack_error ("numeric factorization failed", A_is_complex, + nargout, retval, Control, InfoOut, status, do_info); + return retval; + } + + if (A_is_complex) + (void) umfpack_zi_report_numeric (Numeric, Control_ptr) ; + else + (void) umfpack_di_report_numeric (Numeric, Control_ptr) ; + + // return the solution or the factorization + + if (do_solve) + { + int sys; + ComplexNDArray Xcmplx; + NDArray Xreal; + + // solve Ax=b or A'x'=b', and return just the solution x + +#ifndef NO_TRANSPOSE_FORWARD_SLASH + if (transpose) + { + // A.'x.'=b.' gives the same x=b/A as solving A'x'=b' + // since C=A.' was factorized, solve with sys = UMFPACK_A + // since x and b are vectors, x.' and b.' are implicit + if (X_is_complex) + Xcmplx.resize (dim_vector (1, nn)); + else + Xreal.resize (dim_vector (1, nn)); + } + else + { + if (X_is_complex) + Xcmplx.resize (dim_vector (nn, 1)); + else + Xreal.resize (dim_vector (nn, 1)); + } + + sys = UMFPACK_A ; +#else + if (transpose) + { + // If A is real, A'x=b is the same as A.'x=b. + // x and b are vectors, so x and b are the same as x' and b'. + // If A is complex, then A.'x.'=b.' gives the same solution x + // as the complex conjugate transpose. If we used the A'x=b + // option in umfpack_*_solve, we would have to form b' on + // input and x' on output (negating the imaginary part). + // We can save this work by just using the A.'x=b option in + // umfpack_*_solve. Then, forming x.' and b.' is implicit, + // since x and b are just vectors anyway. + // In both cases, the system to solve is A.'x=b + if (X_is_complex) + Xcmplx.resize (dim_vector (1, nn)); + else + Xreal.resize (dim_vector (1, nn)); + + sys = UMFPACK_Aat ; + } + else + { + if (X_is_complex) + Xcmplx.resize (dim_vector (nn, 1)); + else + Xreal.resize (dim_vector (nn, 1)); + sys = UMFPACK_A ; + } +#endif + + // print the right-hand-side, B + if (print_level >= 3) + octave_stdout << "\nright-hand side, b: "; + + if (B_is_complex) + (void) umfpack_zi_report_vector (nn, Bx, NULL, Control_ptr) ; + else + (void) umfpack_di_report_vector (nn, Bx, Control_ptr) ; + + // solve the system + double * Xx; + if (X_is_complex) + Xx = X_CAST (double *, Xcmplx.fortran_vec ()); + else + Xx = Xreal.fortran_vec (); + status2 = UMFPACK_OK ; + + if (A_is_complex) + { + if (!B_is_complex) + { + OCTAVE_LOCAL_BUFFER (double, Bz, nn); + for (int i = 0; i < nn; i++) + Bz[i] = 0.; + + status = umfpack_zi_solve (sys, Ap, Ai, Ax, NULL, Xx, NULL, + Bx, Bz, Numeric, Control_ptr, + Info); + } + else + status = umfpack_zi_solve (sys, Ap, Ai, Ax, NULL, Xx, NULL, + Bx, NULL, Numeric, Control_ptr, + Info); + } + else + { + if (B_is_complex) + { + // Ax=b when b is complex and A is sparse can be split + // into two systems, A*xr=br and A*xi=bi, where r denotes + // the real part and i the imaginary part of x and b. + OCTAVE_LOCAL_BUFFER (double, Tx, nn); + OCTAVE_LOCAL_BUFFER (double, Tz, nn); + + status = umfpack_di_solve (sys, Ap, Ai, Ax, Tx, Bx, + Numeric, Control_ptr, Info); + status2 = umfpack_di_solve (sys, Ap, Ai, Ax, Tz, Bx, + Numeric, Control_ptr, Info) ; + + for (int i = 0; i < nn; i++) + Xcmplx (i) = Complex (Tx[i], Tz[i]); + } + else + status = umfpack_di_solve (sys, Ap, Ai, Ax, Xx, Bx, + Numeric, Control_ptr, Info); + } + + // free the Numeric object + if (A_is_complex) + umfpack_zi_free_numeric (&Numeric) ; + else + umfpack_di_free_numeric (&Numeric) ; + + // check error status + if (status < 0 || status2 < 0) + { + umfpack_error ("solve failed", A_is_complex, nargout, + retval, Control, InfoOut, status, do_info) ; + return retval; + } + + // print the solution, X + if (print_level >= 3) + octave_stdout << "\nsolution, x: "; + + if (X_is_complex) + (void) umfpack_zi_report_vector (nn, Xx, NULL, Control_ptr); + else + (void) umfpack_di_report_vector (nn, Xx, Control_ptr); + + // warn about singular or near-singular matrices + // no warning is given if Control (1) is zero + if (Control (UMFPACK_PRL) >= 1) + { + if (status == UMFPACK_WARNING_singular_matrix) + { + warning ("matrix is singular"); + warning ("Try increasing Control (%d) and Control (%d).", + 1+UMFPACK_PIVOT_TOLERANCE, + 1+UMFPACK_SYM_PIVOT_TOLERANCE); + warning ("(Suppress this warning with Control (%d) = 0.)", + 1+UMFPACK_PRL); + } + else if (InfoOut (UMFPACK_RCOND) < DBL_EPSILON) + { + warning ("matrix is nearly singular, rcond = %g", + InfoOut (UMFPACK_RCOND)); + warning ("Try increasing Control (%d) and Control (%d).", + 1+UMFPACK_PIVOT_TOLERANCE, + 1+UMFPACK_SYM_PIVOT_TOLERANCE); + warning ("(Suppress this warning with Control (%d) = 0.)", + 1+UMFPACK_PRL); + } + } + + // Setup the return value + if (X_is_complex) + retval (0) = octave_value (Xcmplx); + else + retval (0) = octave_value (Xreal); + } + else + { + // get L, U, P, Q, and r + int lnz, unz, ignore1, ignore2, ignore3; + + if (A_is_complex) + status = umfpack_zi_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + else + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + if (A_is_complex) + umfpack_zi_free_numeric (&Numeric) ; + else + umfpack_di_free_numeric (&Numeric) ; + + umfpack_error ("extracting LU factors failed", A_is_complex, + nargout, retval, Control, InfoOut, status, + do_info); + return retval; + } + + // avoid malloc of zero-sized arrays + lnz = MAX (lnz, 1) ; + unz = MAX (unz, 1) ; + + // get space for the *** ROW *** form of L + SparseMatrix Lreal; + SparseComplexMatrix Limag; + int *Ltp, *Ltj; + double *Ltx; + if (A_is_complex) + { + Limag = SparseComplexMatrix (n_inner, n_row, lnz); + Ltp = Limag.cidx (); + Ltj = Limag.ridx (); + Ltx = X_CAST (double *, Limag.data ()); + } + else + { + Lreal = SparseMatrix (n_inner, n_row, lnz); + Ltp = Lreal.cidx (); + Ltj = Lreal.ridx (); + Ltx = Lreal.data (); + } + + // create permanent copy of the output matrix U + int *Up, *Ui; + double *Ux; + SparseMatrix Ureal; + SparseComplexMatrix Uimag; + + if (A_is_complex) + { + Uimag = SparseComplexMatrix (n_inner, n_col, unz); + Up = Uimag.cidx (); + Ui = Uimag.ridx (); + Ux = X_CAST (double *, Uimag.data ()); + } + else + { + Ureal = SparseMatrix (n_inner, n_col, unz); + Up = Ureal.cidx (); + Ui = Ureal.ridx (); + Ux = Ureal.data (); + } + + // temporary space for the integer permutation vectors + OCTAVE_LOCAL_BUFFER (int, P, n_row); + OCTAVE_LOCAL_BUFFER (int, Q, n_col); + + // get scale factors, if requested + status2 = UMFPACK_OK ; + SparseMatrix Rsout; + double * Rs; + if (!no_scale) + { + // create a diagonal sparse matrix for the scale factors + Rsout = SparseMatrix (n_row, n_row, n_row); + for (int i = 0 ; i < n_row ; i++) + { + Rsout.cidx (i) = i; + Rsout.ridx (i) = i; + } + Rsout.cidx (n_row) = n_row; + Rs = Rsout.data (); + } + else + Rs = (double *) NULL ; + + // get Lt, U, P, Q, and Rs from the numeric object + int do_recip; + if (A_is_complex) + { + status = umfpack_zi_get_numeric (Ltp, Ltj, Ltx, NULL, Up, Ui, + Ux, NULL, P, Q, + (double *) NULL, + (double *) NULL, + &do_recip, Rs, Numeric) ; + umfpack_zi_free_numeric (&Numeric) ; + } + else + { + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Ui, + Ux, P, Q, (double *) NULL, + &do_recip, Rs, Numeric) ; + umfpack_di_free_numeric (&Numeric) ; + } + + if (!no_scale) + retval (4) = octave_vale (Rsout); + + // for the oct-file, -DNRECIPROCAL must be set, + // so do_recip must be FALSE + + if (status < 0 || status2 < 0 || do_recip) + { + umfpack_error ("extracting LU factors failed", A_is_complex, + nargout, retval, Control, InfoOut, status, + do_info); + return retval; + } + + if (A_is_complex) + retval (1) = octave_value (Uimag); + else + retval (1) = octave_valye (Ureal); + + // create sparse permutation matrix for P + SparseMatrix Pout (n_row, n_row, n_row); + for (int k = 0 ; k < n_row ; k++) + { + Pout.cidx (k) = k ; + Pout.ridx (P [k]) = k; + Pout.data (k) = 1; + } + Pout.cidx (n_row) = n_row; + retval (2) = octave_value (Pout); + + // create sparse permutation matrix for Q + SparseMatrix Qout (n_col, n_col, n_col); + for (int k = 0 ; k < n_col ; k++) + { + Qout.cidx (k) = k ; + Qout.ridx (k) = Q[k]; + Qout.data (k) = 1; + } + Qout.cidx (n_col) = n_col; + retval (3) = octave_value (Qout); + + // permanent copy of L + if (A_is_complex) + retval (0) = octave_value (Limag.transpose()); + else + retval (0) = octave_value (Lreal.transpose()); + + if (status < 0) + { + umfpack_error ("constructing L failed", A_is_complex, + nargout, retval, Control, InfoOut, status, + do_info) ; + return octave_value (); + } + + // print L, U, P, and Q + if (A_is_complex) + { + if (print_level >= 3) + { + octave_stdout << "\nL: "; + int *Lp = Limag.cidx (); + int *Li = Limag.ridx (); + double *Lx = X_CAST (double *, Limag.data ()); + + (void) umfpack_zi_report_matrix (n_row, n_inner, Lp, Li, + Lx, NULL, 1, Control_ptr) ; + } + + if (print_level >= 3) + octave_stdout << "\nU: "; + (void) umfpack_zi_report_matrix (n_inner, n_col, Up, Ui, + Ux, NULL, 1, Control_ptr) ; + if (print_level >= 3) + octave_stdout << "\nP: "; + (void) umfpack_zi_report_perm (n_row, P, Control_ptr); + if (print_level >= 3) + octave_stdout << "\nQ: "; + (void) umfpack_zi_report_perm (n_col, Q, Control_ptr); + } + else + { + if (print_level >= 3) + { + int *Lp = Lreal.cidx (); + int *Li = Lreal.ridx (); + double *Lx = Lreal.data (); + octave_stdout << "\nL: "; + (void) umfpack_di_report_matrix (n_row, n_inner, Lp, Li, + Lx, 1, Control_ptr); + } + + if (print_level >= 3) + octave_stdout << "\nU: "; + (void) umfpack_di_report_matrix (n_inner, n_col, Up, Ui, + Ux, 1, Control_ptr); + if (print_level >= 3) + octave_stdout << "\nP: "; + (void) umfpack_di_report_perm (n_row, P, Control_ptr); + if (print_level >= 3) + octave_stdout << "\nQ: "; + (void) umfpack_di_report_perm (n_col, Q, Control_ptr); + } + } + } + else + { + // return the symbolic factorization + int ignore1, ignore2, ignore3; + OCTAVE_LOCAL_BUFFER (int, Q, n_col); + OCTAVE_LOCAL_BUFFER (int, P, n_row); + OCTAVE_LOCAL_BUFFER (int, Front_npivcol, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Front_parent, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Front_1strow, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Front_leftmostdesc, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Chain_start, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Chain_maxrows, nn + 1); + OCTAVE_LOCAL_BUFFER (int, Chain_maxcols, nn + 1); + + int nz, nfronts, nchains; + + if (A_is_complex) + { + status = umfpack_zi_get_symbolic (&ignore1, &ignore2, &ignore3, + &nz, &nfronts, &nchains, P, Q, + Front_npivcol, Front_parent, + Front_1strow, + Front_leftmostdesc, + Chain_start, Chain_maxrows, + Chain_maxcols, Symbolic) ; + umfpack_zi_free_symbolic (&Symbolic) ; + } + else + { + status = umfpack_di_get_symbolic (&ignore1, &ignore2, &ignore3, + &nz, &nfronts, &nchains, P, Q, + Front_npivcol, Front_parent, + Front_1strow, + Front_leftmostdesc, + Chain_start, Chain_maxrows, + Chain_maxcols, Symbolic) ; + umfpack_di_free_symbolic (&Symbolic) ; + } + + if (status < 0) + { + umfpack_error ("extracting symbolic factors failed", + A_is_complex, nargout, retval, Control, + InfoOut, status, do_info) ; + return retval; + } + + // create sparse permutation matrix for P + SparseMatrix Pout (n_row, n_row, n_row); + for (int k = 0 ; k < n_row ; k++) + { + Pout.cidx (k) = k; + Pout.ridx (P [k]) = k; + Pout.data (k) = 1; + } + Pout.cidx (n_row) = n_row; + retval (0) = octave_value (Pout); + + // create sparse permutation matrix for Q + SparseMatrix Qout (n_col, n_col, n_col); + for (int k = 0 ; k < n_col ; k++) + { + Qout.cidx (k) = k; + Qout.ridx (k) = Q[k]; + Qout.data (k) = 1; + } + Qout.cidx (n_col) = n_col; + retval (1) = octave_value (Qout); + + // create Fr + Matrix Frout (nfronts + 1, 4); + for (int i = 0 ; i <= nfronts ; i++) + { + // convert parent, 1strow, and leftmostdesc to 1-based + Frout (i, 0) = (double) (Front_npivcol [i]) ; + Frout (i, 1) = (double) (Front_parent [i] + 1) ; + Frout (i, 2) = (double) (Front_1strow [i] + 1) ; + Frout (i, 3) = (double) (Front_leftmostdesc [i] + 1) ; + } + retval (2) = octave_value (Frout); + + // create Ch + Matrix Chout (nchains + 1, 3); + for (int i = 0 ; i <= nchains ; i++) + { + // convert to 1-based + Chout (i, 0) = (double) (Chain_start [i] + 1) ; + Chout (i, 1) = (double) (Chain_maxrows [i]) ; + Chout (i, 2) = (double) (Chain_maxcols [i]) ; + } + Chout (0, nchains) = (double) Chain_start [nchains] + 1 ; + Chout (1, nchains) = 0.; + Chout (2, nchains) = 0.; + retval (3) = octave_value (Chout); + } + + // report Info + if (A_is_complex) + umfpack_zi_report_info (Control_ptr, Info); + else + umfpack_di_report_info (Control_ptr, Info); + + if (do_info > 0) + retval (do_info) = InfoOut; + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_btf.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_btf.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_btf.m @@ -0,0 +1,129 @@ +function x = umfpack_btf (A, b, Control) +% UMFPACK_BTF +% +% x = umfpack_btf (A, b, Control) +% +% solve Ax=b by first permuting the matrix A to block triangular form via dmperm +% and then using UMFPACK to factorize each diagonal block. Adjacent 1-by-1 +% blocks are merged into a single upper triangular block, and solved via +% MATLAB's \ operator. The Control parameter is optional (Type umfpack_details +% and umfpack_report for details on its use). A must be square. +% +% See also: umfpack, umfpack_factorize, umfpack_details, dmperm + +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. Type umfpack_details for License. + +if (nargin < 2) + help umfpack_btf + error ('Usage: x = umfpack_btf (A, b, Control)') ; +end + +[m n] = size (A) ; +if (m ~= n) + help umfpack_btf + error ('umfpack_btf: A must be square') ; +end +[m1 n1] = size (b) ; +if (m1 ~= n) + help umfpack_btf + error ('umfpack_btf: b has the wrong dimensions') ; +end + +if (nargin < 3) + Control = umfpack ; +end + +%------------------------------------------------------------------------------- +% find the block triangular form +%------------------------------------------------------------------------------- + +[p,q,r] = dmperm (A) ; +nblocks = length (r) - 1 ; + +%------------------------------------------------------------------------------- +% solve the system +%------------------------------------------------------------------------------- + +if (nblocks == 1 | sprank (A) < n) + + %--------------------------------------------------------------------------- + % matrix is irreducible or structurally singular + %--------------------------------------------------------------------------- + + x = umfpack_solve (A, '\\', b, Control) ; + +else + + %--------------------------------------------------------------------------- + % A (p,q) is in block triangular form + %--------------------------------------------------------------------------- + + b = b (p,:) ; + A = A (p,q) ; + x = zeros (size (b)) ; + + %--------------------------------------------------------------------------- + % merge adjacent singletons into a single upper triangular block + %--------------------------------------------------------------------------- + + [r, nblocks, is_triangular] = merge_singletons (r) ; + + %--------------------------------------------------------------------------- + % solve the system: x (q) = A\b + %--------------------------------------------------------------------------- + + for k = nblocks:-1:1 + + % get the kth block + k1 = r (k) ; + k2 = r (k+1) - 1 ; + + % solve the system + x (k1:k2,:) = solver (A (k1:k2, k1:k2), b (k1:k2,:), ... + is_triangular (k), Control) ; + + % off-diagonal block back substitution + b (1:k1-1,:) = b (1:k1-1,:) - A (1:k1-1, k1:k2) * x (k1:k2,:) ; + + end + + x (q,:) = x ; + +end + +%------------------------------------------------------------------------------- +% merge_singletons +%------------------------------------------------------------------------------- + +function [r, nblocks, is_triangular] = merge_singletons (r) +% +% Given r from [p,q,r] = dmperm (A), where A is square, return a modified r that +% reflects the merger of adjacent singletons into a single upper triangular +% block. is_triangular (k) is 1 if the kth block is upper triangular. nblocks +% is the number of new blocks. + +nblocks = length (r) - 1 ; +bsize = r (2:nblocks+1) - r (1:nblocks) ; +t = [0 (bsize == 1)] ; +z = (t (1:nblocks) == 0 & t (2:nblocks+1) == 1) | t (2:nblocks+1) == 0 ; +y = [(find (z)) nblocks+1] ; +r = r (y) ; +nblocks = length (y) - 1 ; +is_triangular = y (2:nblocks+1) - y (1:nblocks) > 1 ; + +%------------------------------------------------------------------------------- +% solve Ax=b, but check for small and/or triangular systems +%------------------------------------------------------------------------------- + +function x = solver (A, b, is_triangular, Control) +if (is_triangular) + % back substitution only + x = A \ b ; +elseif (size (A,1) < 4) + % a very small matrix, solve it as a dense linear system + x = full (A) \ b ; +else + % solve it as a sparse linear system + x = umfpack_solve (A, '\\', b, Control) ; +end diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m @@ -0,0 +1,191 @@ +function umfpack_demo +% UMFPACK DEMO +% +% A demo of UMFPACK for OCTAVE. +% +% See also umfpack, umfpack_make, umfpack_details, umfpack_report, +% and umfpack_simple. + +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. Type umfpack_details for License. + +%------------------------------------------------------------------------------- +% get default control parameters +%------------------------------------------------------------------------------- + +control = umfpack ; +fprintf ('\nEnter the printing level for UMFPACK''s output statistics:\n') ; +fprintf ('0: none, 1: errors only, 2: statistics, 4: print some of outputs\n') ; +c = input ('5: print all output [default is 1]: ') ; +if (isempty (c)) + c = 1 ; +end +control (1) = c ; + +%------------------------------------------------------------------------------- +% solve a simple system +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Factor and solve a small system, Ax=b, using default parameters\n') ; +if (control (1) > 1) + fprintf ('(except for verbose printing enabled)\n') ; +end + +load west0067 ; +A = Problem.A ; +n = size (A, 1) ; +b = rand (n, 1) ; + +fprintf ('Solving Ax=b via UMFPACK:\n') ; +[xu, info] = umfpack (A, '\\', b, control) ; +x = xu ; + +fprintf ('Solving Ax=b via OCTAVE:\n') ; +xm = A\b ; +x = xm ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% spy the results +%------------------------------------------------------------------------------- + +figure (1) ; +clf + +subplot (2,3,1) +title ('The matrix A') ; +spy (A) + +subplot (2,3,2) +[P1, Q1, Fr, Ch, Info] = umfpack (A, 'symbolic') ; +title ('Supernodal column elimination tree') ; +%% Disable for now !! +%% treeplot (Fr (1:end-1,2)') ; + +subplot (2,3,3) +title ('A, with initial row and column order') ; +spy (P1 * A * Q1) + +subplot (2,3,4) +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nFactorizing [L, U, P, Q, R] = umfpack (A)\n') ; +[L, U, P, Q, R] = umfpack (A) ; +title ('A, with final row/column order') ; +spy (P*A*Q) + +fprintf ('\nP * (R\\A) * Q - L*U should be zero:\n') ; +fprintf ('norm (P*(R\\A)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... + norm (P * (R\A) * Q - L*U, 1), lu_normest (P * (R\A) * Q, L, U)) ; + +fprintf ('\nSolution to Ax=b via UMFPACK factorization:\n') ; +fprintf ('x = Q * (U \\ (L \\ (P * (R \\ b))))\n') ; +xu = Q * (U \ (L \ (P * (R \ b)))) ; +x = xu ; + +fprintf ('\nUMFPACK flop count: %d\n', luflop (L, U)) ; + +subplot (2,3,5) +title ('UMFPACK LU factors') ; +spy (spones (L) + spones (U)) + +subplot (2,3,6) +fprintf ('\nFactorizing [L, U, P] = lu (A (:, q))\n') ; +try + q = colamd (A) ; +catch + fprintf ('\n *** colamd not found, using colmmd instead *** \n') ; + q = colmmd (A) ; +end +[L, U, P] = lu (A (:,q)) ; +title ('OCTAVE LU factors') ; +spy (spones (L) + spones (U)) + +fprintf ('\nSolution to Ax=b via OCTAVE factorization:\n') ; +fprintf ('x = U \\ (L \\ (P * b)) ; x (q) = x ;\n') ; +xm = U \ (L \ (P * b)) ; +xm (q) = xm ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (xu - xm, Inf)) ; + +fprintf ('\nOCTAVE LU flop count: %d\n', luflop (L, U)) ; + +%------------------------------------------------------------------------------- +% solve A'x=b +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Solve A''x=b:\n') ; + +fprintf ('Solving A''x=b via UMFPACK:\n') ; +[xu, info] = umfpack (b', '/', A, control) ; +xu = xu' ; + +fprintf ('Solving A''x=b via OCTAVE:\n') ; +xm = (b'/A)' ; +x = xm ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% factor A' and then solve Ax=b using the factors of A' +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Compute C = A'', and compute the LU factorization of C.\n') ; +fprintf ('Factorizing A'' can sometimes be better than factorizing A itself\n'); +fprintf ('(less work and memory usage). Solve C''x=b; the solution is the\n') ; +fprintf ('same as the solution to Ax=b for the original A.\n'); + +C = A' ; + +% factorize C (P,Q) = L*U +[L, U, P, Q, R, info] = umfpack (C, control) ; + +fprintf ('\nP * (R\\C) * Q - L*U should be zero:\n') ; +fprintf ('norm (P*(R\\C)*Q - L*U, 1) = %g (exact) %g (estimated)\n', ... + norm (P * (R\C) * Q - L*U, 1), lu_normest (P * (R\C) * Q, L, U)) ; + +fprintf ('\nSolution to Ax=b via UMFPACK, using the factors of C:\n') ; +fprintf ('x = R \\ (P'' * (L'' \\ (U'' \\ (Q'' * b)))) ;\n') ; +xu = R \ (P' * (L' \ (U' \ (Q' * b)))) ; +x = xu ; + +fprintf ('Solution to Ax=b via OCTAVE:\n') ; +xm = A\b ; +x = xm ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (xu - xm, Inf)) ; + +%------------------------------------------------------------------------------- +% solve Ax=B +%------------------------------------------------------------------------------- + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve AX=B, where B is n-by-10, and sparse\n') ; +B = sprandn (n, 10, 0.05) ; +XU = umfpack_solve (A, '\\', B, control) ; +XM = A\B ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (XU - XM, Inf)) ; + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve AX=B, where B is n-by-10, and sparse, using umfpack_btf\n') ; +XU = umfpack_btf (A, B, control) ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (XU - XM, Inf)) ; + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('\nSolve A''X=B, where B is n-by-10, and sparse\n') ; +XU = umfpack_solve (B', '/', A, control) ; +XM = B'/A ; + +fprintf ('Difference between UMFPACK and OCTAVE solution: %g\n', ... + norm (XU - XM, Inf)) ; diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m.out b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_demo.m.out @@ -0,0 +1,72 @@ +>> umfpack_demo + +Enter the printing level for UMFPACK's output statistics: +0: none, 1: errors only, 2: statistics, 4: print some of outputs +5: print all output [default is 1]: + +-------------------------------------------------------------- +Factor and solve a small system, Ax=b, using default parameters +Solving Ax=b via UMFPACK: +Solving Ax=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 1.24345e-14 + +-------------------------------------------------------------- + +Factorizing [L, U, P, Q, R] = umfpack (A) + +P * (R\A) * Q - L*U should be zero: +norm (P*(R\A)*Q - L*U, 1) = 4.2068e-16 (exact) 3.74627e-16 (estimated) + +Solution to Ax=b via UMFPACK factorization: +x = Q * (U \ (L \ (P * (R \ b)))) + +UMFPACK flop count: 2362 + +Factorizing [L, U, P] = lu (A (:, q)) +If you are using a version of MATLAB prior to V6.0, then the +following statement (q = colamd (A)) may fail. Either download +colamd from http://www.cise.ufl.edu/research/sparse, upgrade to +MATLAB V6.0 or later, or replace the statement with +q = colmmd (A) ; + +Solution to Ax=b via MATLAB factorization: +x = U \ (L \ (P * b)) ; x (q) = x ; +Difference between UMFPACK and MATLAB solution: 1.37668e-14 + +MATLAB LU flop count: 3164 + +-------------------------------------------------------------- +Solve A'x=b: +Solving A'x=b via UMFPACK: +Solving A'x=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 3.10862e-15 + +-------------------------------------------------------------- +Compute C = A', and compute the LU factorization of C. +Factorizing A' can sometimes be better than factorizing A itself +(less work and memory usage). Solve C'x=b; the solution is the +same as the solution to Ax=b for the original A. + +P * (R\C) * Q - L*U should be zero: +norm (P*(R\C)*Q - L*U, 1) = 1.31839e-16 (exact) 6.41848e-17 (estimated) + +Solution to Ax=b via UMFPACK, using the factors of C: +x = R \ (P' * (L' \ (U' \ (Q' * b)))) ; +Solution to Ax=b via MATLAB: +Difference between UMFPACK and MATLAB solution: 1.77636e-14 + +-------------------------------------------------------------- + +Solve AX=B, where B is n-by-10, and sparse +Difference between UMFPACK and MATLAB solution: 2.88198e-14 + +-------------------------------------------------------------- + +Solve AX=B, where B is n-by-10, and sparse, using umfpack_btf +Difference between UMFPACK and MATLAB solution: 9.79736e-14 + +-------------------------------------------------------------- + +Solve A'X=B, where B is n-by-10, and sparse +Difference between UMFPACK and MATLAB solution: 1.05244e-13 +>> diary off diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_make.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_make.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_make.m @@ -0,0 +1,356 @@ +function umfpack_make +% UMFPACK_MAKE +% +% Compiles the UMFPACK mexFunction and then runs a simple demo. +% +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. Type umfpack_details for License. +% +% See also: umfpack, umfpack_details, umfpack_report, umfpack_demo, and +% umfpack_simple. + +help umfpack_make + +fprintf ('\n--------------------------------------------------------------\n') ; +fprintf ('Now compiling the UMFPACK and AMD mexFunctions.\n') ; +fprintf ('--------------------------------------------------------------\n') ; + +try + % ispc does not appear in MATLAB 5.3 + pc = ispc ; +catch + % if ispc fails, assume we aren't on a Windows PC. + pc = 0 ; +end + +obj = 'o' ; +blas_lib = '' ; +if (pc) + obj = 'obj' ; +end + +%------------------------------------------------------------------------------- +% BLAS option +%------------------------------------------------------------------------------- + +msg = [ ... + '\nUsing the BLAS is faster, but might not compile correctly.\n', ... + 'If you get an error stating that dgemm, dgemv, dger, zgemm,\n', ... + 'zgemv, and/or zger are not defined, then recompile without the\n', ... + 'BLAS. You can ignore warnings that these routines are implicitly\n', ... + 'declared.\n\nPlease select one of the following options: \n', ... + ' 1: attempt to compile with the BLAS (default)\n', ... + ' 2: do not use the BLAS\n'] ; +fprintf (msg) ; +blas = input (': ') ; +if (isempty (blas)) + blas = 1 ; +end +if (blas == 1) + % try to link to MATLAB's built-in BLAS + blas = '' ; + if (pc) + % the default lcc compiler needs this library to access the BLAS + blas_lib = ' libmwlapack.lib' ; + msg = [ ... + '\nCheck to see if you have a file called libmwlapack.lib in the\n', ... + '\\extern\\lib\\win32\\lcc\\ directory, where is ', ... + 'the\ndirectory where MATLAB is installed. If a file of that ', ... + 'name is already\nthere, then you don''t have to do anything. ', ... + 'Otherwise, you must first\ncopy the libmwlapack.lib file from ', ... + 'the umfpack\\lcc_lib\\ directory to the\n', ... + '\\extern\\lib\\win32\\lcc\\ directory. Next, type\n\n', ... + ' mex -setup\n\n', ... + 'at the MATLAB prompt, and ask MATLAB to select the lcc compiler. ',... + 'You can skip\nall of this if you have already done it, or have ', ... + 'configured mex to use\na different compiler. If you are using ', ... + 'Norton anti-virus software on Windows\n98SE, then you need to ', ... + 'exit MATLAB, turn off virus checking, and restart MATLAB\n', ... + 'before you can use the mex command or compile UMFPACK.\n', ... + 'You may also need to turn off virus checking in other cases.\n', ... + '\nHit enter to continue, or type control-C if you do not wish to '] ; + fprintf (msg) ; + input ('proceed: ') ; + end + fprintf ('\nUsing the BLAS (recommended).\n') ; +else + % No BLAS + fprintf ('\nNot using the BLAS. UMFPACK will be slow.\n') ; + blas = ' -DNBLAS' ; +end + +%------------------------------------------------------------------------------- +% -DNUTIL option (using utMalloc or mxMalloc) +%------------------------------------------------------------------------------- + +utils = '' ; + +if (~pc) + msg = [ ... + '--------------------------------------------------------------\n', ... + '\nUMFPACK uses MATLAB''s memory allocation routines. The internal', ... + '\nutMalloc, utFree, and utRealloc allow for better use of memory,', ... + '\nbut they are internal utility routines that are not documented.\n', ... + 'Thus, they might not always work. Using mxMalloc, mxFree, and\n', ... + 'mxRealloc works, but UMFPACK might run out of memory when solving\n', ... + 'problems that it could otherwise solve. Try using the default.\n', ... + 'If you get an error stating that utMalloc, utFree, and/or\n', ... + 'utRealloc are not defined, then recompile with the mx* routines.\n', ... + '\nPlease select one of the following options:\n', ... + ' 1: attempt to use the ut* routines (default)\n', ... + ' 2: use the standard mx* routines\n'] ; + fprintf (msg) ; + utils = input (': ') ; + if (isempty (utils)) + utils = 1 ; + end + if (utils == 2) + fprintf ('\nNot using utMalloc, utFree, or utRealloc\n') ; + utils = ' -DNUTIL' ; + else + fprintf ('\nUsing utMalloc, utFree, and utRealloc\n') ; + utils = '' ; + end +end + +%------------------------------------------------------------------------------- +% -DNPOSIX option (for sysconf and times timer routines) +%------------------------------------------------------------------------------- + +posix = '' ; + +if (~pc) + msg = [ ... + '--------------------------------------------------------------\n', ... + '\nUMFPACK can use the POSIX routines sysconf () and times ()\n', ... + 'to provide CPU time and wallclock time statistics. If you do not\n', ... + 'have a POSIX-compliant operating system, then UMFPACK won''t\n', ... + 'compile. If you don''t know which option to pick, try the\n', ... + 'default. If you get an error saying that sysconf and/or times\n', ... + 'are not defined, then recompile with the non-POSIX option.\n', ... + '\nPlease select one of the following options:\n', ... + ' 1: use POSIX sysconf and times routines (default)\n', ... + ' 2: do not use POSIX routines\n'] ; + fprintf (msg) ; + posix = input (': ') ; + if (isempty (posix)) + posix = 1 ; + end + if (posix == 2) + fprintf ('\nNot using POSIX sysconf and times routines.\n') ; + posix = ' -DNPOSIX' ; + else + fprintf ('\nUsing POSIX sysconf and times routines.\n') ; + posix = '' ; + end +end + +%------------------------------------------------------------------------------- +% mex command +%------------------------------------------------------------------------------- + +umfdir = sprintf ('..%sSource%s', filesep, filesep) ; +amddir = sprintf ('..%s..%sAMD%sSource%s', filesep, filesep, filesep, filesep) ; +incdir = sprintf ( ... +' -I..%sInclude -I..%sSource -I..%s..%sAMD%sInclude -I..%s..%sAMD%sSource', ... +filesep,filesep, filesep, filesep, filesep, filesep, filesep, filesep) ; + +mx = sprintf ('mex -inline -O%s%s%s%s', blas, utils, posix, incdir) ; +msg = [ ... + '--------------------------------------------------------------\n', ... + '\nCompile options:\n%s\nNow compiling. Please wait.\n'] ; +fprintf (msg, mx) ; + +% The following is adapted from GNUmakefile + +%------------------------------------------------------------------------------- +% source files +%------------------------------------------------------------------------------- + +% non-user-callable umf_*.[ch] files: +umfch = { 'assemble', 'blas3_update', ... + 'build_tuples', 'create_element', ... + 'dump', 'extend_front', 'garbage_collection', ... + 'get_memory', 'init_front', 'kernel', ... + 'kernel_init', 'kernel_wrapup', ... + 'local_search', 'lsolve', 'ltsolve', ... + 'mem_alloc_element', 'mem_alloc_head_block', ... + 'mem_alloc_tail_block', 'mem_free_tail_block', ... + 'mem_init_memoryspace', ... + 'report_vector', 'row_search', 'scale_column', ... + 'set_stats', 'solve', 'symbolic_usage', 'transpose', ... + 'tuple_lengths', 'usolve', 'utsolve', 'valid_numeric', ... + 'valid_symbolic', 'grow_front', 'start_front', '2by2', ... + 'store_lu', 'scale' } ; + +% non-user-callable umf_*.[ch] files, int versions only (no real/complex): +umfint = { 'analyze', 'apply_order', 'colamd', 'free', 'fsize', ... + 'is_permutation', 'malloc', 'realloc', 'report_perm', ... + 'singletons' } ; + +% non-user-callable and user-callable amd_*.[ch] files (int versions only): +amd = { 'aat', '1', '2', 'dump', 'postorder', 'post_tree', 'defaults', ... + 'order', 'control', 'info', 'valid' } ; + +% user-callable umfpack_*.[ch] files (real/complex): +user = { 'col_to_triplet', 'defaults', 'free_numeric', ... + 'free_symbolic', 'get_numeric', 'get_lunz', ... + 'get_symbolic', 'numeric', 'qsymbolic', ... + 'report_control', 'report_info', 'report_matrix', ... + 'report_numeric', 'report_perm', 'report_status', ... + 'report_symbolic', 'report_triplet', ... + 'report_vector', 'solve', 'symbolic', ... + 'transpose', 'triplet_to_col', 'scale' ... + 'load_numeric', 'save_numeric', 'load_symbolic', 'save_symbolic' } ; + +% user-callable umfpack_*.[ch], only one version +generic = { 'timer', 'tictoc' } ; + +M = cell (0) ; + +%------------------------------------------------------------------------------- +% Create the umfpack and amd mexFunctions for MATLAB (int versions only) +%------------------------------------------------------------------------------- + +for k = 1:length(umfint) + M = make (M, '%s -DDINT -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... + mx, umfint {k}, umfint {k}, 'm', obj, umfdir) ; +end + +rules = { [mx ' -DDINT'] , [mx ' -DZINT'] } ; +kinds = { 'md', 'mz' } ; + +for what = 1:2 + + rule = rules {what} ; + kind = kinds {what} ; + + M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s.%s', rule, 'ltsolve', 'lhsolve', kind, obj, umfdir) ; + + M = make (M, '%s -DCONJUGATE_SOLVE -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s.%s', rule, 'utsolve', 'uhsolve', kind, obj, umfdir) ; + + M = make (M, '%s -DDO_MAP -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_map_nox.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_nomap_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_nomap_nox.%s', rule, 'triplet', 'triplet', kind, obj, ... + umfdir) ; + + M = make (M, '%s -DDO_MAP -DDO_VALUES -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_map_x.%s', rule, 'triplet', 'triplet', kind, obj, umfdir) ; + + M = make (M, '%s -DFIXQ -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_fixq.%s', rule, 'assemble', 'assemble', kind, obj, umfdir) ; + + M = make (M, '%s -DDROP -c %sumf_%s.c', 'umf_%s.%s', ... + 'umf_%s_%s_drop.%s', rule, 'store_lu', 'store_lu', kind, obj, umfdir) ; + + for k = 1:length(umfch) + M = make (M, '%s -c %sumf_%s.c', 'umf_%s.%s', 'umf_%s_%s.%s', ... + rule, umfch {k}, umfch {k}, kind, obj, umfdir) ; + end + + M = make (M, '%s -DWSOLVE -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_w%s.%s', rule, 'solve', 'solve', kind, obj, umfdir) ; + + for k = 1:length(user) + M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_%s.%s', rule, user {k}, user {k}, kind, obj, umfdir) ; + end +end + +for k = 1:length(generic) + M = make (M, '%s -c %sumfpack_%s.c', 'umfpack_%s.%s', ... + 'umfpack_%s_%s.%s', mx, generic {k}, generic {k}, 'm', obj, umfdir) ; +end + +%---------------------------------------- +% AMD routines (int only) +%---------------------------------------- + +for k = 1:length(amd) + M = make (M, '%s -DDINT -c %samd_%s.c', 'amd_%s.%s', 'amd_%s_%s.%s', ... + mx, amd {k}, amd {k}, 'm', obj, amddir) ; +end + +%---------------------------------------- +% compile the umfpack mexFunction +%---------------------------------------- + +C = sprintf ('%s -output umfpack umfpackmex.c', mx) ; +for i = 1:length (M) + C = [C ' ' (M {i})] ; +end +C = [C ' ' blas_lib] ; +cmd (C) ; + +%---------------------------------------- +% delete the object files +%---------------------------------------- + +for i = 1:length (M) + rmfile (M {i}) ; +end + +%---------------------------------------- +% compile the luflop mexFunction +%---------------------------------------- + +cmd (sprintf ('%s -output luflop luflopmex.c', mx)) ; + +fprintf ('\n\nCompilation has completed. Now trying the umfpack_simple demo.\n'); +umfpack_simple + +%------------------------------------------------------------------------------- +% rmfile: delete a file, but only if it exists +%------------------------------------------------------------------------------- + +function rmfile (file) +if (length (dir (file)) > 0) + delete (file) ; +end + +%------------------------------------------------------------------------------- +% cpfile: copy the src file to the filename dst, overwriting dst if it exists +%------------------------------------------------------------------------------- + +function cpfile (src, dst) +rmfile (dst) +if (length (dir (src)) == 0) + help umfpack_make + error (sprintf ('File does not exist: %s\n', src)) ; +end +copyfile (src, dst) ; + +%------------------------------------------------------------------------------- +% mvfile: move the src file to the filename dst, overwriting dst if it exists +%------------------------------------------------------------------------------- + +function mvfile (src, dst) +cpfile (src, dst) ; +rmfile (src) ; + +%------------------------------------------------------------------------------- +% cmd: display and execute a command +%------------------------------------------------------------------------------- + +function cmd (s) +fprintf ('.') ; +eval (s) ; + +%------------------------------------------------------------------------------- +% make: execute a "make" command for a source file +%------------------------------------------------------------------------------- + +function M = make (M, s, src, dst, rule, file1, file2, kind, obj, srcdir) +cmd (sprintf (s, rule, srcdir, file1)) ; +src = sprintf (src, file1, obj) ; +dst = sprintf (dst, kind, file2, obj) ; +mvfile (src, dst) ; +M {end + 1} = dst ; + diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_report.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_report.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_report.m @@ -0,0 +1,346 @@ +function umfpack_report (Control, Info) +% UMFPACK_REPORT +% +% umfpack_report (Control, Info) ; +% +% Prints the current Control settings for umfpack, and the statistical +% information returned by umfpack in the Info array. If Control is +% an empty matrix, then the default control settings are printed. +% +% Control is 20-by-1, and Info is 90-by-1. Not all entries are used. +% +% Alternative usages: +% +% umfpack_report ([ ], Info) ; print the default control parameters +% and the Info array. +% umfpack_report (Control) ; print the control parameters only. +% umfpack_report ; print the default control parameters +% and an empty Info array. +% +% See also umfpack, umfpack_make, umfpack_details, +% umfpack_demo, and umfpack_simple. + +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. See ../README for License. + +%------------------------------------------------------------------------------- +% get inputs, use defaults if input arguments not present +%------------------------------------------------------------------------------- + +% The contents of Control and Info are defined in umfpack.h +if (nargin < 1) + Control = [] ; +end +if (nargin < 2) + Info = [] ; +end +if (isempty (Control)) + Control = umfpack ; +end +if (isempty (Info)) + Info = [ 0 (-ones (1, 89)) ] ; +end + +%------------------------------------------------------------------------------- +% control settings +%------------------------------------------------------------------------------- + +fprintf ('\nUMFPACK Version 4.3: Control settings:\n\n') ; +fprintf (' Control (1): print level: %d\n', Control (1)) ; +fprintf (' Control (2): dense row parameter: %g\n', Control (2)) ; +fprintf (' "dense" rows have > max (16, (%g)*16*sqrt(n_col)) entries\n', Control (2)) ; +fprintf (' Control (3): dense column parameter: %g\n', Control (3)) ; +fprintf (' "dense" columns have > max (16, (%g)*16*sqrt(n_row)) entries\n', Control (3)) ; +fprintf (' Control (4): pivot tolerance: %g\n', Control (4)) ; +fprintf (' Control (5): max block size for dense matrix kernels: %d\n', Control (5)) ; +prstrat (' Control (6): strategy: %g ', Control (6)) ; +fprintf (' Control (7): initial allocation ratio: %g\n', Control (7)) ; +fprintf (' Control (8): max iterative refinement steps: %d\n', Control (8)) ; +fprintf (' Control (13): 2-by-2 pivot tolerance: %g\n', Control (13)) ; +fprintf (' Control (14): Q fixed during numeric factorization: %g ', Control (14)) ; +if (Control (14) > 0) + fprintf ('(yes)\n') ; +elseif (Control (14) < 0) + fprintf ('(no)\n') ; +else + fprintf ('(auto)\n') ; +end +fprintf (' Control (15): AMD dense row/column parameter: %g\n', Control (15)) ; +fprintf (' "dense" rows/columns in A+A'' have > max (16, (%g)*sqrt(n)) entries.\n', Control (15)) ; +fprintf (' Only used if the AMD ordering is used.\n') ; +fprintf (' Control (16): diagonal pivot tolerance: %g\n', Control (16)) ; +fprintf (' Only used if diagonal pivoting is attempted.\n') ; + +fprintf (' Control (17): scaling option: %g ', Control (17)) ; +if (Control (17) == 0) + fprintf ('(none)\n') ; +elseif (Control (17) == 2) + fprintf ('(scale the matrix by\n') ; + fprintf (' dividing each row by max. abs. value in each row)\n') ; +else + fprintf ('(scale the matrix by\n') ; + fprintf (' dividing each row by sum of abs. values in each row)\n') ; +end + +fprintf (' Control (18): frontal matrix allocation ratio: %g\n', Control (18)) ; +fprintf (' Control (19): drop tolerance: %g\n', Control (19)) ; +fprintf (' Control (20): AMD and COLAMD aggressive absorption: %g ', Control (20)) ; +yes_no (Control (20)) ; + +% compile-time options: + +fprintf ('\n The following options can only be changed at compile-time:\n') ; + +if (Control (9) == 1) + fprintf (' Control (9): compiled to use the BLAS\n') ; +else + fprintf (' Control (9): compiled without the BLAS\n') ; + fprintf (' (you will not get the best possible performance)\n') ; +end + +if (Control (10) == 1) + fprintf (' Control (10): compiled for MATLAB\n') ; +elseif (Control (10) == 2) + fprintf (' Control (10): compiled for MATLAB\n') ; + fprintf (' Uses internal utMalloc, utFree, utRealloc, utPrintf\n') ; + fprintf (' utDivideComplex, and utFdlibm_hypot routines.\n') ; +else + fprintf (' Control (10): not compiled for MATLAB\n') ; + fprintf (' Uses ANSI C malloc, free, realloc, and printf\n') ; + fprintf (' instead of mxMalloc, mxFree, mxRealloc, and mexPrintf.\n') ; + fprintf (' Printing will be in terms of 0-based matrix indexing,\n') ; + fprintf (' not 1-based as is expected in MATLAB. Diary output may\n') ; + fprintf (' not be properly recorded.\n') ; +end + +if (Control (11) == 2) + fprintf (' Control (11): uses POSIX times ( ) to get CPU time and wallclock time.\n') ; +elseif (Control (11) == 1) + fprintf (' Control (11): uses getrusage to get CPU time.\n') ; +else + fprintf (' Control (11): uses ANSI C clock to get CPU time.\n') ; + fprintf (' The CPU time may wrap around, type "help cputime".\n') ; +end + +if (Control (12) == 1) + fprintf (' Control (12): compiled with debugging enabled\n') ; + fprintf (' ###########################################\n') ; + fprintf (' ### This will be exceedingly slow! ########\n') ; + fprintf (' ###########################################\n') ; + if (Control (10) == 1) + fprintf (' Uses mxAssert.\n') ; + elseif (Control (10) == 2) + fprintf (' Uses utAssert.\n') ; + else + fprintf (' Uses ANSI C assert instead of mxAssert.\n') ; + end +else + fprintf (' Control (12): compiled for normal operation (no debugging)\n') ; +end + +%------------------------------------------------------------------------------- +% Info: +%------------------------------------------------------------------------------- + +if (nargin == 1) + return +end + +status = Info (1) ; +fprintf ('\nUMFPACK status: Info (1): %d, ', status) ; + +if (status == 0) + fprintf ('OK\n') ; +elseif (status == 1) + fprintf ('WARNING matrix is singular\n') ; +elseif (status == -1) + fprintf ('ERROR out of memory\n') ; +elseif (status == -3) + fprintf ('ERROR numeric LU factorization is invalid\n') ; +elseif (status == -4) + fprintf ('ERROR symbolic LU factorization is invalid\n') ; +elseif (status == -5) + fprintf ('ERROR required argument is missing\n') ; +elseif (status == -6) + fprintf ('ERROR n <= 0\n') ; +elseif (status <= -7 & status >= -12 | status == -14) + fprintf ('ERROR matrix A is corrupted\n') ; +elseif (status == -13) + fprintf ('ERROR invalid system\n') ; +elseif (status == -15) + fprintf ('ERROR invalid permutation\n') ; +elseif (status == -911) + fprintf ('ERROR internal error!\n') ; + fprintf ('Please report this error to Tim Davis (davis@cise.ufl.edu)\n') ; +else + fprintf ('ERROR unrecognized error. Info array corrupted\n') ; +end + +fprintf (' (a -1 means the entry has not been computed):\n') ; + +fprintf ('\n Basic statistics:\n') ; +fprintf (' Info (2): %d, # of rows of A\n', Info (2)) ; +fprintf (' Info (17): %d, # of columns of A\n', Info (17)) ; +fprintf (' Info (3): %d, nnz (A)\n', Info (3)) ; +fprintf (' Info (4): %d, Unit size, in bytes, for memory usage reported below\n', Info (4)) ; +fprintf (' Info (5): %d, size of int (in bytes)\n', Info (5)) ; +fprintf (' Info (6): %d, size of long (in bytes)\n', Info (6)) ; +fprintf (' Info (7): %d, size of pointer (in bytes)\n', Info (7)) ; +fprintf (' Info (8): %d, size of numerical entry (in bytes)\n', Info (8)) ; + +fprintf ('\n Pivots with zero Markowitz cost removed to obtain submatrix S:\n') ; +fprintf (' Info (57): %d, # of pivots with one entry in pivot column\n', Info (57)) ; +fprintf (' Info (58): %d, # of pivots with one entry in pivot row\n', Info (58)) ; +fprintf (' Info (59): %d, # of rows/columns in submatrix S (if square)\n', Info (59)) ; +fprintf (' Info (60): %d ') ; +if (Info (60) > 0) + fprintf ('submatrix S square and diagonal preserved\n') ; +elseif (Info (60) == 0) + fprintf ('submatrix S not square or diagonal not preserved\n') ; +else + fprintf ('\n') ; +end +fprintf (' Info (9): %d, # of "dense" rows in S\n', Info (9)) ; +fprintf (' Info (10): %d, # of empty rows in S\n', Info (10)) ; +fprintf (' Info (11): %d, # of "dense" columns in S\n', Info (11)) ; +fprintf (' Info (12): %d, # of empty columns in S\n', Info (12)) ; +fprintf (' Info (34): %g, symmetry of pattern of S\n', Info (34)) ; +fprintf (' Info (35): %d, # of off-diagonal nonzeros in S+S''\n', Info (35)) ; +fprintf (' Info (36): %d, nnz (diag (S))\n', Info (36)) ; + +fprintf ('\n 2-by-2 pivoting to place large entries on diagonal:\n') ; +fprintf (' Info (52): %d, # of small diagonal entries of S\n', Info (52)) ; +fprintf (' Info (53): %d, # of unmatched small diagonal entries\n', Info (53)) ; +fprintf (' Info (54): %g, symmetry of P2*S\n', Info (54)) ; +fprintf (' Info (55): %d, # of off-diagonal entries in (P2*S)+(P2*S)''\n', Info (55)) ; +fprintf (' Info (56): %d, nnz (diag (P2*S))\n', Info (56)) ; + +fprintf ('\n AMD results, for strict diagonal pivoting:\n') ; +fprintf (' Info (37): %d, est. nz in L and U\n', Info (37)) ; +fprintf (' Info (38): %g, est. flop count\n', Info (38)) ; +fprintf (' Info (39): %g, # of "dense" rows in S+S''\n', Info (39)) ; +fprintf (' Info (40): %g, est. max. nz in any column of L\n', Info (40)) ; + +fprintf ('\n Final strategy selection, based on the analysis above:\n') ; +prstrat (' Info (19): %d, strategy used ', Info (19)) ; +fprintf (' Info (20): %d, ordering used ', Info (20)) ; +if (Info (20) == 0) + fprintf ('(COLAMD on A)\n') ; +elseif (Info (20) == 1) + fprintf ('(AMD on A+A'')\n') ; +elseif (Info (20) == 2) + fprintf ('(provided by user)\n') ; +else + fprintf ('(undefined ordering option)\n') ; +end +fprintf (' Info (32): %d, Q fixed during numeric factorization: ', Info (32)) ; +yes_no (Info (32)) ; +fprintf (' Info (33): %d, prefer diagonal pivoting: ', Info (33)) ; +yes_no (Info (33)) ; + +fprintf ('\n symbolic analysis time and memory usage:\n') ; +fprintf (' Info (13): %d, defragmentations during symbolic analysis\n', Info (13)) ; +fprintf (' Info (14): %d, memory used during symbolic analysis (Units)\n', Info (14)) ; +fprintf (' Info (15): %d, final size of symbolic factors (Units)\n', Info (15)) ; +fprintf (' Info (16): %.2f, symbolic analysis CPU time (seconds)\n', Info (16)) ; +fprintf (' Info (18): %.2f, symbolic analysis wall clock time (seconds)\n', Info (18)) ; + +fprintf ('\n Estimates computed in the symbolic analysis:\n') ; +fprintf (' Info (21): %d, est. size of LU factors (Units)\n', Info (21)) ; +fprintf (' Info (22): %d, est. total peak memory usage (Units)\n', Info (22)) ; +fprintf (' Info (23): %d, est. factorization flop count\n', Info (23)) ; +fprintf (' Info (24): %d, est. nnz (L)\n', Info (24)) ; +fprintf (' Info (25): %d, est. nnz (U)\n', Info (25)) ; +fprintf (' Info (26): %d, est. initial size, variable-part of LU (Units)\n', Info (26)) ; +fprintf (' Info (27): %d, est. peak size, of variable-part of LU (Units)\n', Info (27)) ; +fprintf (' Info (28): %d, est. final size, of variable-part of LU (Units)\n', Info (28)) ; +fprintf (' Info (29): %d, est. max frontal matrix size (# of entries)\n', Info (29)) ; +fprintf (' Info (30): %d, est. max # of rows in frontal matrix\n', Info (30)) ; +fprintf (' Info (31): %d, est. max # of columns in frontal matrix\n', Info (31)) ; + +fprintf ('\n Computed in the numeric factorization (estimates shown above):\n') ; +fprintf (' Info (41): %d, size of LU factors (Units)\n', Info (41)) ; +fprintf (' Info (42): %d, total peak memory usage (Units)\n', Info (42)) ; +fprintf (' Info (43): %d, factorization flop count\n', Info (43)) ; +fprintf (' Info (44): %d, nnz (L)\n', Info (44)) ; +fprintf (' Info (45): %d, nnz (U)\n', Info (45)) ; +fprintf (' Info (46): %d, initial size of variable-part of LU (Units)\n', Info (46)) ; +fprintf (' Info (47): %d, peak size of variable-part of LU (Units)\n', Info (47)) ; +fprintf (' Info (48): %d, final size of variable-part of LU (Units)\n', Info (48)) ; +fprintf (' Info (49): %d, max frontal matrix size (# of numerical entries)\n', Info (49)) ; +fprintf (' Info (50): %d, max # of rows in frontal matrix\n', Info (50)) ; +fprintf (' Info (51): %d, max # of columns in frontal matrix\n', Info (51)) ; + +fprintf ('\n Computed in the numeric factorization (no estimates computed a priori):\n') ; +fprintf (' Info (61): %d, defragmentations during numeric factorization\n', Info (61)) ; +fprintf (' Info (62): %d, reallocations during numeric factorization\n', Info (62)) ; +fprintf (' Info (63): %d, costly reallocations during numeric factorization\n', Info (63)) ; +fprintf (' Info (64): %d, integer indices in compressed pattern of L and U\n', Info (64)) ; +fprintf (' Info (65): %d, numerical values stored in L and U\n', Info (65)) ; +fprintf (' Info (66): %.2f, numeric factorization CPU time (seconds)\n', Info (66)) ; +fprintf (' Info (76): %.2f, numeric factorization wall clock time (seconds)\n', Info (76)) ; +if (Info (66) > 0.05 & Info (43) > 0) +fprintf (' mflops in numeric factorization phase: %.2f\n', 1e-6 * Info (43) / Info (66)) ; +end +fprintf (' Info (67): %d, nnz (diag (U))\n', Info (67)) ; +fprintf (' Info (68): %g, reciprocal condition number estimate\n', Info (68)) ; +fprintf (' Info (69): %g, matrix was ', Info (69)) ; +if (Info (69) == 0) + fprintf ('not scaled\n') ; +elseif (Info (69) == 2) + fprintf ('scaled (row max)\n') ; +else + fprintf ('scaled (row sum)\n') ; +end +fprintf (' Info (70): %g, min. scale factor of rows of A\n', Info (70)) ; +fprintf (' Info (71): %g, max. scale factor of rows of A\n', Info (71)) ; +fprintf (' Info (72): %g, min. abs. on diagonal of U\n', Info (72)) ; +fprintf (' Info (73): %g, max. abs. on diagonal of U\n', Info (73)) ; +fprintf (' Info (74): %g, initial allocation parameter used\n', Info (74)) ; +fprintf (' Info (75): %g, # of forced updates due to frontal growth\n', Info (75)) ; +fprintf (' Info (77): %d, # of off-diaogonal pivots\n', Info (77)) ; +fprintf (' Info (78): %d, nnz (L), if no small entries dropped\n', Info (78)) ; +fprintf (' Info (79): %d, nnz (U), if no small entries dropped\n', Info (79)) ; +fprintf (' Info (80): %d, # of small entries dropped\n', Info (80)) ; + +fprintf ('\n Computed in the solve step:\n') ; +fprintf (' Info (81): %d, iterative refinement steps taken\n', Info (81)) ; +fprintf (' Info (82): %d, iterative refinement steps attempted\n', Info (82)) ; +fprintf (' Info (83): %g, omega(1), sparse-backward error estimate\n', Info (83)) ; +fprintf (' Info (84): %g, omega(2), sparse-backward error estimate\n', Info (84)) ; +fprintf (' Info (85): %d, solve flop count\n', Info (85)) ; +fprintf (' Info (86): %.2f, solve CPU time (seconds)\n', Info (86)) ; +fprintf (' Info (87): %.2f, solve wall clock time (seconds)\n', Info (87)) ; + +fprintf ('\n Info (88:90): unused\n\n') ; + +%------------------------------------------------------------------------------- + +function prstrat (fmt, strategy) +fprintf (fmt, strategy) ; +if (strategy == 1) + fprintf ('(unsymmetric)\n') ; + fprintf (' Q = COLAMD (A), Q refined during numerical\n') ; + fprintf (' factorization, and no attempt at diagonal pivoting.\n') ; +elseif (strategy == 2) + fprintf ('(symmetric, with 2-by-2 pivoting)\n') ; + fprintf (' P2 = row permutation to place large values on the diagonal\n') ; + fprintf (' Q = AMD (P2*A+(P2*A)''), Q not refined during numeric factorization,\n') ; + fprintf (' and diagonal pivoting attempted.\n') ; +elseif (strategy == 3) + fprintf ('(symmetric)\n') ; + fprintf (' Q = AMD (A+A''), Q not refined during numeric factorization,\n') ; + fprintf (' and diagonal pivoting (P=Q'') attempted.\n') ; +else + strategy = 0 ; + fprintf ('(auto)\n') ; +end + +%------------------------------------------------------------------------------- + +function yes_no (s) +if (s == 0) + fprintf ('(no)\n') ; +else + fprintf ('(yes)\n') ; +end diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m @@ -0,0 +1,61 @@ +% umfpack_simple: a simple demo of UMFPACK +% +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. +% +% UMFPACK License: +% +% Your use or distribution of UMFPACK or any modified version of +% UMFPACK implies that you agree to this License. +% +% THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +% EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +% +% Permission is hereby granted to use or copy this program, provided +% that the Copyright, this License, and the Availability of the original +% version is retained on all copies. User documentation of any code that +% uses UMFPACK or any modified version of UMFPACK code must cite the +% Copyright, this License, the Availability note, and "Used by permission." +% Permission to modify the code and to distribute modified code is granted, +% provided the Copyright, this License, and the Availability note are +% retained, and a notice that the code was modified is included. This +% software was developed with support from the National Science Foundation, +% and is provided to you free of charge. +% +% Availability: http://www.cise.ufl.edu/research/sparse/umfpack +% +% See also: umfpack, umfpack_details + +help umfpack_simple +i = input ('Hit enter to agree to the above License: ', 's') ; +if (~isempty (i)) + error ('terminating') ; +end + +format short + +A = [ + 2 3 0 0 0 + 3 0 4 0 6 + 0 -1 -3 2 0 + 0 0 1 0 0 + 0 4 2 0 1 +] + +A = sparse (A) ; + +b = [8 45 -3 3 19]' + +fprintf ('Solution to Ax=b via UMFPACK:\n') ; +fprintf ('x1 = umfpack (A, ''\\'', b)\n') ; + +x1 = umfpack (A, '\\', b) + +fprintf ('Solution to Ax=b via OCTAVE:\n') ; +fprintf ('x2 = A\\b\n') ; + +x2 = A\b + +fprintf ('norm (x1-x2) should be small: %g\n', norm (x1-x2)) ; + +fprintf ('Type ''umfpack_demo'' for a full demo of UMFPACK\n') ; diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m.out b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m.out new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_simple.m.out @@ -0,0 +1,79 @@ +octave:4> umfpack_simple +umfpack_simple is the file: /home/dbateman/octave/devel/octave-sparse/UMFPACKv4.3/UMFPACK/OCTAVE/umfpack_simple.m + +umfpack_simple: a simple demo of UMFPACK + +UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +Davis. All Rights Reserved. + +UMFPACK License: + + Your use or distribution of UMFPACK or any modified version of + UMFPACK implies that you agree to this License. + + THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY + EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + + Permission is hereby granted to use or copy this program, provided + that the Copyright, this License, and the Availability of the original + version is retained on all copies. User documentation of any code that + uses UMFPACK or any modified version of UMFPACK code must cite the + Copyright, this License, the Availability note, and "Used by permission." + Permission to modify the code and to distribute modified code is granted, + provided the Copyright, this License, and the Availability note are + retained, and a notice that the code was modified is included. This + software was developed with support from the National Science Foundation, + and is provided to you free of charge. + +Availability: http://www.cise.ufl.edu/research/sparse/umfpack + +See also: umfpack, umfpack_details + + +Additional help for built-in functions, operators, and variables +is available in the on-line version of the manual. Use the command +`help -i ' to search the manual index. + +Help and information about Octave is also available on the WWW +at http://www.octave.org and via the help@octave.org +mailing list. +Hit enter to agree to the above License: +A = + + 2 3 0 0 0 + 3 0 4 0 6 + 0 -1 -3 2 0 + 0 0 1 0 0 + 0 4 2 0 1 + +b = + + 8 + 45 + -3 + 3 + 19 + +Solution to Ax=b via UMFPACK: +x1 = umfpack (A, '\', b) +x1 = + + 1.00000 + 2.00000 + 3.00000 + 4.00000 + 5.00000 + +Solution to Ax=b via OCTAVE: +x2 = A\b +x2 = + + 1.00000 + 2.00000 + 3.00000 + 4.00000 + 5.00000 + +norm (x1-x2) should be small: 0 +Type 'umfpack_demo' for a full demo of UMFPACK +octave:5> diary off diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_solve.m b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_solve.m new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/OCTAVE/umfpack_solve.m @@ -0,0 +1,97 @@ +function x = umfpack_solve (arg1, op, arg2, Control) +% UMFPACK_SOLVE +% +% x = umfpack_solve (A, '\', b, Control) +% x = umfpack_solve (b, '/', A, Control) +% +% Computes x = A\b, or b/A, where A is square. Uses UMFPACK if A is sparse. +% The Control argument is optional. +% +% See also umfpack, umfpack_make, umfpack_details, umfpack_report, +% and umfpack_simple. + +% UMFPACK Version 4.3 (Jan. 16, 2004), Copyright (c) 2004 by Timothy A. +% Davis. All Rights Reserved. Type umfpack_details for License. + +%------------------------------------------------------------------------------- +% check inputs and get default control parameters +%------------------------------------------------------------------------------- + +if (op == '\\') + A = arg1 ; + b = arg2 ; +elseif (op == '/') + A = arg2 ; + b = arg1 ; +else + help umfack_solve + error ('umfpack_solve: unrecognized operator') ; +end + +[m n] = size (A) ; +if (m ~= n) + help umfpack_solve + error ('umfpack_solve: A must be square') ; +end + +[m1 n1] = size (b) ; +if ((op == '\\' & n ~= m1) | (op == '/' & n1 ~= m)) + help umfpack_solve + error ('umfpack_solve: b has the wrong dimensions') ; +end + +if (nargin < 4) + Control = umfpack ; +end + +%------------------------------------------------------------------------------- +% solve the system +%------------------------------------------------------------------------------- + +if (op == '\\') + + if (~issparse (A)) + + % A is not sparse, so just use MATLAB + x = A\b ; + + elseif (n1 == 1 & ~issparse (b)) + + % the UMFPACK '\' requires b to be a dense column vector + x = umfpack (A, '\\', b, Control) ; + + else + + % factorize with UMFPACK and do the forward/back solves in MATLAB + [L, U, P, Q, R] = umfpack (A, Control) ; + keyboard + x = Q * (U \ (L \ (P * (R \ b)))) ; + + end + +else + + if (~issparse (A)) + + % A is not sparse, so just use MATLAB + x = b/A ; + + elseif (m1 == 1 & ~issparse (b)) + + % the UMFPACK '/' requires b to be a dense column vector + x = umfpack (b, '/', A, Control) ; + + else + + % factorize with UMFPACK and do the forward/back solves in MATLAB + % this mimics the behavior of x = b/A, except for the row scaling + [L, U, P, Q, R] = umfpack (A.', Control) ; + x = (Q * (U \ (L \ (P * (R \ (b.')))))).' ; + + % an alternative method: + % [L, U, P, Q, r] = umfpack (A, Control) ; + % x = (R \ (P' * (L.' \ (U.' \ (Q' * b.'))))).' ; + + end + +end diff --git a/liboctave/UMFPACK/UMFPACK/OCTAVE/west0067.mat b/liboctave/UMFPACK/UMFPACK/OCTAVE/west0067.mat new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f3ebe28e0d29427d7069466803f34b8996a4dcc5 GIT binary patch literal 4043 zc$~eLc~DeG5QiTsm$IB9C_+|66uHA8ATTSqiU&s!VyPsefJ!3BvEE{NVJrzm1uL2Z z57Z)_#8@CMFyP4{XFNdELNOr{MNL^TL?h|p^?L$~75|97st=~Sf8Fz@-^^A`P^4o1 z@@P9JyBVA&$8o`lOBXDOj^)_XsR4hI6p70s75!nP22A7w5*CP`pO_Rajh(MZj9K}r zv$N9=oD3_qE)h2n&;<;EA;2)e92g0V2F3z5fIZ*{xB{L40VVxrz@NYij&F)Opbh8(hQJVD7+?X6P~-bC0Ho>w>nLlp7GMet#lDyU!#Q3z7-L?T zV~jd4%olp;g|$pD-wW#w$8leCa_D!*@2QUCeyC&P{-}4y9QST{+W1{Py5%$9AoK}! zm`?|NLOte_pic{JU9_>4UHSdH#m3`&gRq_i{d#~tV8HSF%LsMM?}>VS9P6OY6Y~vm ztc!V`m^TU-!}0r%v`im!Ws6)`o@@V z(rq3)z=`93FW4OHjDLtWtM33fqs?lw^Y4N-tL=*8zScAbzl$~Y-v)Ke?}PfWIF_Q$ z2lL0_cqHceyrG^GzOOUB7keLJf7oJN#=YJnwy0-5VV~GyKJy8C#TM(ya2{K%EyMbj zm~VwKp^t8WZ?`@Qw$Mkx7WydIuHD9VnD2l(=GWZZ<`}=Np^oP0#jPDbrjB0J?l)|1 zaTPtL^(fWT`U3Sxlf9~N%B8%nl<>Mz@@-b>lexu3B*CgV&(r!e;dT4SH+$IgfNu9l znVuZ<~Hy4cTijT@btMIG8IIw77N95KDoxmG1^wZY`_&P~^7SY6DR%$jFJj)F)f;1qHdoMs$C`f}h_0jwbEb!nOsu3=fAFgG zjw`1bFYONdxL%}58{ItC)>E>gVbVhT_!7b$nw)lGMF|;k^~Kt0n~RBh-KJpEqynKX zb?$mv#ChJezv>EmZjlRz6o024X~*?8zxQ}=zfxbL!)0Ry^-7#`*m&0!y4`<0+3#0H zzidsm>v&L3&)tovFjJP&x7G3UJQ4r*od4bVGc5X9Y-&19_7*lehUyg%m!*ylW`7lu zdzl3tlNCioeYKJH<(zzS#A0@Og>62`eA!}Z*`OqA($}@=nwAiYX9nL7{G^1~{^~Ti zbn01>Cb|7kZ*T|BcVDn+gO9y3VR)<9KaHE_Av*fcL><~Hx;t|peq?0YF6z)$(Ip&A zF4EDzFY3@%(e;d9Rf+%C?{&}pT1!S9HOSS8Xj9oY?^ntge@kknG>h%VkPBGqwJ)PSknI>nf>tO8$bIhIN$J z)ly~qasL^$|B#c(;mcdx?+~;pZ?}u{+R2(eyWaR*)S<1S+q*+6Eu!VAs6$&t7dbk0 z-}S~;QHQpQu4nv)N_@Ft-lU(`RZz>5Nh^{@k>2BdBAJ)2%e)#`53 z^RKF@#OT!SWWQQb$1Xu}^JAmCOyPnY6Ss(6fY}9xT|E4K9acmqDI6W$#Ew_g(8yMemory + umf_get_memory.[ch] make Numeric->Memory bigger + umf_grow_front.[ch] make current frontal matrix bigger + umf_init_front.[ch] initialize a new frontal matrix + umf_is_permutation.[ch] checks the validity of a permutation vector + umf_kernel.[ch] the main numeric factorization kernel + umf_kernel_init.[ch] initializations for umf_kernel + umf_kernel_wrapup.[ch] wrapup for umf_kernel + umf_local_search.[ch] local row and column pivot search + umf_lsolve.[ch] solve Lx=b + umf_ltsolve.[ch] solve L'x=b and L.'x=b + umf_malloc.[ch] malloc some memory + umf_mem_alloc_element.[ch] allocate element in Numeric->Memory + umf_mem_alloc_head_block.[ch] alloc. block at head of Numeric->Memory + umf_mem_alloc_tail_block.[ch] alloc. block at tail of Numeric->Memory + umf_mem_free_tail_block.[ch] free block at tail of Numeric->Memory + umf_mem_init_memoryspace.[ch] initialize Numeric->Memory + umf_realloc.[ch] realloc memory + umf_report_perm.[ch] print a permutation vector + umf_report_vector.[ch] print a double vector + umf_row_search.[ch] look for a pivot row + umf_scale.[ch] scale the pivot column + umf_scale_column.[ch] move pivot row & column into place, log P and Q + umf_set_stats.[ch] set statistics (final or estimates) + umf_singletons.[ch] find all zero-cost pivots + umf_solve.[ch] solve a linear system + umf_start_front.[ch] start a new frontal matrix for one frontal chain + umf_store_lu.[ch] store LU factors of current front + umf_symbolic_usage.[ch] determine memory usage for Symbolic object + umf_transpose.[ch] transpose a matrix in row or col form + umf_triplet.[ch] convert triplet to column form + umf_tuple_lengths.[ch] determine the tuple list lengths + umf_usolve.[ch] solve Ux=b + umf_utsolve.[ch] solve U'x=b and U.'x=b + umf_valid_numeric.[ch] checks the validity of a Numeric object + umf_valid_symbolic.[ch] check the validity of a Symbolic object + + ---------------------------------------------------------------------------- + Include directory: + ---------------------------------------------------------------------------- + + umfpack.h include file for user programs. Includes all of + the following files. This serves are source- + code level documenation. These files are also + used to construct the User Guide. + + umfpack_col_to_triplet.h + umfpack_defaults.h + umfpack_free_numeric.h + umfpack_free_symbolic.h + umfpack_get_determinant.h + umfpack_get_lunz.h + umfpack_get_numeric.h + umfpack_get_symbolic.h + umfpack_load_numeric.h + umfpack_load_symbolic.h + umfpack_numeric.h + umfpack_qsymbolic.h + umfpack_report_control.h + umfpack_report_info.h + umfpack_report_matrix.h + umfpack_report_numeric.h + umfpack_report_perm.h + umfpack_report_status.h + umfpack_report_symbolic.h + umfpack_report_triplet.h + umfpack_report_vector.h + umfpack_save_numeric.h + umfpack_save_symbolic.h + umfpack_scale.h + umfpack_solve.h + umfpack_symbolic.h + umfpack_tictoc.h + umfpack_timer.h + umfpack_transpose.h + umfpack_triplet_to_col.h + + umfpack_wsolve.h note that there is no umfpack_wsolve.c. The + umfpack_*_wsolve routines are created from the + umfpack_solve.c file. + + ---------------------------------------------------------------------------- + Demo directory: + ---------------------------------------------------------------------------- + + Makefile for GNU make or original make + + umfpack_simple.c a simple demo + umpack_xx_demo.c template to create the demo codes below + + umfpack_di_demo.sed for creating umfpack_di_demo.c + umfpack_dl_demo.sed for creating umfpack_dl_demo.c + umfpack_zi_demo.sed for creating umfpack_zi_demo.c + umfpack_zl_demo.sed for creating umfpack_zl_demo.c + + umfpack_di_demo.c a full demo (real/int version) + umfpack_dl_demo.c a full demo (real/long version) + umfpack_zi_demo.c a full demo (complex/int version) + umfpack_zl_demo.c a full demo (complex/long version) + + umfpack_di_demo.out umfpack_di_demo output, unmodified Make.include + umfpack_dl_demo.out umfpack_dl_demo output, unmodified Make.include + umfpack_zi_demo.out umfpack_zi_demo output, unmodified Make.include + umfpack_zl_demo.out umfpack_zl_demo output, unmodified Make.include + + umf4.c a demo (real/int) for Harwell/Boeing matrices + umf4.out output of "make hb", unmodified Make.include + HB directory of sample Harwell/Boeing matrices + readhb.f reads HB matrices, keeps zero entries + readhb_nozeros.f reads HB matrices, removes zero entries + readhb_size.f reads HB matrix dimension, nnz + tmp empty directory for umf4.c demo + + umf4_f77wrapper.c a simple FORTRAN interface for UMFPACK. + compile with "make fortran" + umf4hb.f a demo of the FORTRAN interface + umf4hb.out output of "make fortran" + + umf4_f77zwrapper.c a simple FORTRAN interface for the complex + UMFPACK routines. compile with "make fortran" + umf4zhb.f a demo of the FORTRAN interface (complex) + umf4zhb.out output of umf4zhb with HB/qc324.cua + + umf4hb64.f 64-bit version of umf4hb.f + + simple_compile a single command that compiles the double/int + version of UMFPACK (useful prototype for + Microsoft Visual Studio project) + + ---------------------------------------------------------------------------- + MATLAB directory: + ---------------------------------------------------------------------------- + + Contents.m for "help umfpack" listing of toolbox contents + GNUmakefile a nice Makefile, for GNU make + Makefile an ugly Unix Makefile (for older make's) + + lu_normest.m 1-norm estimate of A-L*U (by Hager & Davis). + luflop.m for "help luflop" + luflopmex.c luflop mexFunction, for computing LU flop count + umfpack.m for "help umfpack" + umfpack_btf.m solve Ax=b using umfpack and dmperm + umfpack_demo.m a full umfpack demo + umfpack_details.m the details of how to use umfpack + umfpack_make.m compile the umfpack mexFunction within MATLAB + umfpack_report.m report statistics + umfpack_simple.m a simple umfpack demo + umfpack_solve.m x=A\b or b/A for arbitrary b + umfpack_test.m extensive test, requires UF sparse matrices + umfpackmex.c the umfpack mexFunction + west0067.mat sparse matrix for umfpack_demo.m + + umfpack_demo.m.out output of umfpack_demo.m + umfpack_simple.m.out output of umfpack_simple + + lcc_lib/lapacksyms.def LAPACK definitions for lcc compiler (Windows) + lcc_lib/libmwlapack.lib LAPACK definitions for lcc compiler (Windows) + + ---------------------------------------------------------------------------- + Lib directory: libumfpack.a library placed here + ---------------------------------------------------------------------------- + + libumfpack.def UMPFACK definitions for Windows diff --git a/liboctave/UMFPACK/UMFPACK/Source/GNUmakefile b/liboctave/UMFPACK/UMFPACK/Source/GNUmakefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/GNUmakefile @@ -0,0 +1,253 @@ +#------------------------------------------------------------------------------- +# UMFPACK Makefile for compiling on Unix systems (for GNU Make) +#------------------------------------------------------------------------------- + +all: ../Lib/libumfpack.a + +include ../Make/Make.include + +C = $(CC) $(CFLAGS) $(CONFIG) -I../Include -I../../AMD/Include -I../../AMD/Source + +#------------------------------------------------------------------------------- +# source files +#------------------------------------------------------------------------------- + +# non-user-callable umf_*.[ch] files: +UMFCH = umf_assemble umf_blas3_update umf_build_tuples umf_create_element \ + umf_dump umf_extend_front umf_garbage_collection umf_get_memory \ + umf_init_front umf_kernel umf_kernel_init umf_kernel_wrapup \ + umf_local_search umf_lsolve umf_ltsolve umf_mem_alloc_element \ + umf_mem_alloc_head_block umf_mem_alloc_tail_block \ + umf_mem_free_tail_block umf_mem_init_memoryspace \ + umf_report_vector umf_row_search umf_scale_column \ + umf_set_stats umf_solve umf_symbolic_usage umf_transpose \ + umf_tuple_lengths umf_usolve umf_utsolve umf_valid_numeric \ + umf_valid_symbolic umf_grow_front umf_start_front umf_2by2 \ + umf_store_lu umf_scale + +# non-user-callable umf_*.[ch] files, int/long versions only (no real/complex): +UMFINT = umf_analyze umf_apply_order umf_colamd umf_free umf_fsize \ + umf_is_permutation umf_malloc umf_realloc umf_report_perm \ + umf_singletons + +# non-user-callable, created from umf_ltsolve.c, umf_utsolve.c, +# umf_triplet.c, and umf_assemble.c , with int/long and real/complex versions: +UMF_CREATED = umf_lhsolve umf_uhsolve umf_triplet_map_nox \ + umf_triplet_nomap_x umf_triplet_nomap_nox umf_triplet_map_x \ + umf_assemble_fixq umf_store_lu_drop + +# non-user-callable, int/long and real/complex versions: +UMF = $(UMF_CREATED) $(UMFCH) + +# user-callable umfpack_*.[ch] files (int/long and real/complex): +UMFPACK = umfpack_col_to_triplet umfpack_defaults umfpack_free_numeric \ + umfpack_free_symbolic umfpack_get_numeric umfpack_get_lunz \ + umfpack_get_symbolic umfpack_get_determinant umfpack_numeric \ + umfpack_qsymbolic umfpack_report_control umfpack_report_info \ + umfpack_report_matrix umfpack_report_numeric umfpack_report_perm \ + umfpack_report_status umfpack_report_symbolic umfpack_report_triplet \ + umfpack_report_vector umfpack_solve umfpack_symbolic \ + umfpack_transpose umfpack_triplet_to_col umfpack_scale \ + umfpack_load_numeric umfpack_save_numeric \ + umfpack_load_symbolic umfpack_save_symbolic + +# user-callable, created from umfpack_solve.c (umfpack_wsolve.h exists, though): +# with int/long and real/complex versions: +UMFPACKW = umfpack_wsolve + +USER = $(UMFPACKW) $(UMFPACK) + +# user-callable, only one version for int/long, real/complex, *.[ch] files: +GENERIC = umfpack_timer umfpack_tictoc + +#------------------------------------------------------------------------------- +# include files: +#------------------------------------------------------------------------------- + +INC = ../Include/umfpack.h \ + umf_config.h umf_version.h umf_internal.h umf_triplet.h \ + $(addsuffix .h,$(UMFCH)) \ + $(addsuffix .h,$(UMFINT)) \ + $(addprefix ../Include/, $(addsuffix .h,$(USER))) \ + $(addprefix ../Include/, $(addsuffix .h,$(GENERIC))) \ + ../../AMD/Source/amd_internal.h ../../AMD/Include/amd.h + +#------------------------------------------------------------------------------- +# object files for each version +#------------------------------------------------------------------------------- + +DI = $(addsuffix .o, $(subst umf_,umf_di_,$(UMF)) $(subst umfpack_,umfpack_di_,$(USER))) +DL = $(addsuffix .o, $(subst umf_,umf_dl_,$(UMF)) $(subst umfpack_,umfpack_dl_,$(USER))) +ZI = $(addsuffix .o, $(subst umf_,umf_zi_,$(UMF)) $(subst umfpack_,umfpack_zi_,$(USER))) +ZL = $(addsuffix .o, $(subst umf_,umf_zl_,$(UMF)) $(subst umfpack_,umfpack_zl_,$(USER))) +I = $(addsuffix .o, $(subst umf_,umf_i_,$(UMFINT))) +L = $(addsuffix .o, $(subst umf_,umf_l_,$(UMFINT))) +GN = $(addsuffix .o, $(subst umfpack_,umfpack_gn_,$(GENERIC))) + +#------------------------------------------------------------------------------- +# compile each int and long routine (with no real/complex version) +#------------------------------------------------------------------------------- + +umf_i_%.o: umf_%.c $(INC) + $(C) -DDINT -c $< -o $@ + +umf_l_%.o: umf_%.c $(INC) + $(C) -DDLONG -c $< -o $@ + +#------------------------------------------------------------------------------- +# compile each routine in the DI version +#------------------------------------------------------------------------------- + +umf_di_%.o: umf_%.c $(INC) + $(C) -DDINT -c $< -o $@ + +umf_di_%hsolve.o: umf_%tsolve.c $(INC) + $(C) -DDINT -DCONJUGATE_SOLVE -c $< -o $@ + +umf_di_triplet_map_x.o: umf_triplet.c $(INC) + $(C) -DDINT -DDO_MAP -DDO_VALUES -c $< -o $@ + +umf_di_triplet_map_nox.o: umf_triplet.c $(INC) + $(C) -DDINT -DDO_MAP -c $< -o $@ + +umf_di_triplet_nomap_x.o: umf_triplet.c $(INC) + $(C) -DDINT -DDO_VALUES -c $< -o $@ + +umf_di_triplet_nomap_nox.o: umf_triplet.c $(INC) + $(C) -DDINT -c $< -o $@ + +umf_di_assemble_fixq.o: umf_assemble.c $(INC) + $(C) -DDINT -DFIXQ -c $< -o $@ + +umf_di_store_lu_drop.o: umf_store_lu.c $(INC) + $(C) -DDINT -DDROP -c $< -o $@ + +umfpack_di_wsolve.o: umfpack_solve.c $(INC) + $(C) -DDINT -DWSOLVE -c $< -o $@ + +umfpack_di_%.o: umfpack_%.c $(INC) + $(C) -DDINT -c $< -o $@ + +#------------------------------------------------------------------------------- +# compile each routine in the DL version +#------------------------------------------------------------------------------- + +umf_dl_%.o: umf_%.c $(INC) + $(C) -DDLONG -c $< -o $@ + +umf_dl_%hsolve.o: umf_%tsolve.c $(INC) + $(C) -DDLONG -DCONJUGATE_SOLVE -c $< -o $@ + +umf_dl_triplet_map_x.o: umf_triplet.c $(INC) + $(C) -DDLONG -DDO_MAP -DDO_VALUES -c $< -o $@ + +umf_dl_triplet_map_nox.o: umf_triplet.c $(INC) + $(C) -DDLONG -DDO_MAP -c $< -o $@ + +umf_dl_triplet_nomap_x.o: umf_triplet.c $(INC) + $(C) -DDLONG -DDO_VALUES -c $< -o $@ + +umf_dl_triplet_nomap_nox.o: umf_triplet.c $(INC) + $(C) -DDLONG -c $< -o $@ + +umf_dl_assemble_fixq.o: umf_assemble.c $(INC) + $(C) -DDLONG -DFIXQ -c $< -o $@ + +umf_dl_store_lu_drop.o: umf_store_lu.c $(INC) + $(C) -DDLONG -DDROP -c $< -o $@ + +umfpack_dl_wsolve.o: umfpack_solve.c $(INC) + $(C) -DDLONG -DWSOLVE -c $< -o $@ + +umfpack_dl_%.o: umfpack_%.c $(INC) + $(C) -DDLONG -c $< -o $@ + +#------------------------------------------------------------------------------- +# compile each routine in the ZI version +#------------------------------------------------------------------------------- + +umf_zi_%.o: umf_%.c $(INC) + $(C) -DZINT -c $< -o $@ + +umf_zi_%hsolve.o: umf_%tsolve.c $(INC) + $(C) -DZINT -DCONJUGATE_SOLVE -c $< -o $@ + +umf_zi_triplet_map_x.o: umf_triplet.c $(INC) + $(C) -DZINT -DDO_MAP -DDO_VALUES -c $< -o $@ + +umf_zi_triplet_map_nox.o: umf_triplet.c $(INC) + $(C) -DZINT -DDO_MAP -c $< -o $@ + +umf_zi_triplet_nomap_x.o: umf_triplet.c $(INC) + $(C) -DZINT -DDO_VALUES -c $< -o $@ + +umf_zi_triplet_nomap_nox.o: umf_triplet.c $(INC) + $(C) -DZINT -c $< -o $@ + +umf_zi_assemble_fixq.o: umf_assemble.c $(INC) + $(C) -DZINT -DFIXQ -c $< -o $@ + +umf_zi_store_lu_drop.o: umf_store_lu.c $(INC) + $(C) -DZINT -DDROP -c $< -o $@ + +umfpack_zi_wsolve.o: umfpack_solve.c $(INC) + $(C) -DZINT -DWSOLVE -c $< -o $@ + +umfpack_zi_%.o: umfpack_%.c $(INC) + $(C) -DZINT -c $< -o $@ + +#------------------------------------------------------------------------------- +# compile each routine in the ZL version +#------------------------------------------------------------------------------- + +umf_zl_%.o: umf_%.c $(INC) + $(C) -DZLONG -c $< -o $@ + +umf_zl_%hsolve.o: umf_%tsolve.c $(INC) + $(C) -DZLONG -DCONJUGATE_SOLVE -c $< -o $@ + +umf_zl_triplet_map_x.o: umf_triplet.c $(INC) + $(C) -DZLONG -DDO_MAP -DDO_VALUES -c $< -o $@ + +umf_zl_triplet_map_nox.o: umf_triplet.c $(INC) + $(C) -DZLONG -DDO_MAP -c $< -o $@ + +umf_zl_triplet_nomap_x.o: umf_triplet.c $(INC) + $(C) -DZLONG -DDO_VALUES -c $< -o $@ + +umf_zl_triplet_nomap_nox.o: umf_triplet.c $(INC) + $(C) -DZLONG -c $< -o $@ + +umf_zl_assemble_fixq.o: umf_assemble.c $(INC) + $(C) -DZLONG -DFIXQ -c $< -o $@ + +umf_zl_store_lu_drop.o: umf_store_lu.c $(INC) + $(C) -DZLONG -DDROP -c $< -o $@ + +umfpack_zl_wsolve.o: umfpack_solve.c $(INC) + $(C) -DZLONG -DWSOLVE -c $< -o $@ + +umfpack_zl_%.o: umfpack_%.c $(INC) + $(C) -DZLONG -c $< -o $@ + +#------------------------------------------------------------------------------- +# Create the generic routines (GN) using a generic rule +#------------------------------------------------------------------------------- + +umfpack_gn_%.o: umfpack_%.c $(INC) + $(C) -c $< -o $@ + +#------------------------------------------------------------------------------- +# Create the libumfpack.a library +#------------------------------------------------------------------------------- + +../Lib/libumfpack.a: $(I) $(L) $(GN) $(DI) $(DL) $(ZI) $(ZL) + $(AR) cr ../Lib/libumfpack.a $^ + - $(RANLIB) ../Lib/libumfpack.a + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) ../Lib/libumfpack.a diff --git a/liboctave/UMFPACK/UMFPACK/Source/Makefile b/liboctave/UMFPACK/UMFPACK/Source/Makefile new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/Makefile @@ -0,0 +1,479 @@ +#------------------------------------------------------------------------------- +# UMFPACK Makefile for compiling on Unix systems (for original make only) +#------------------------------------------------------------------------------- + +# This is a very ugly Makefile, and is only provided for those who do not +# have GNU make. Note that it is not used if you have GNU make. It ignores +# dependency checking and just compiles everything. It was created +# automatically, via make -n using the GNUmakefile. That way, I don't have +# maintain two Makefiles. + +all: everything + +include ../Make/Make.include + +C = $(CC) $(CFLAGS) $(CONFIG) -I../Include -I../../AMD/Include -I../../AMD/Source + +everything: + $(C) -DDINT -c umf_analyze.c -o umf_i_analyze.o + $(C) -DDINT -c umf_apply_order.c -o umf_i_apply_order.o + $(C) -DDINT -c umf_colamd.c -o umf_i_colamd.o + $(C) -DDINT -c umf_free.c -o umf_i_free.o + $(C) -DDINT -c umf_fsize.c -o umf_i_fsize.o + $(C) -DDINT -c umf_is_permutation.c -o umf_i_is_permutation.o + $(C) -DDINT -c umf_malloc.c -o umf_i_malloc.o + $(C) -DDINT -c umf_realloc.c -o umf_i_realloc.o + $(C) -DDINT -c umf_report_perm.c -o umf_i_report_perm.o + $(C) -DDINT -c umf_singletons.c -o umf_i_singletons.o + $(C) -DDLONG -c umf_analyze.c -o umf_l_analyze.o + $(C) -DDLONG -c umf_apply_order.c -o umf_l_apply_order.o + $(C) -DDLONG -c umf_colamd.c -o umf_l_colamd.o + $(C) -DDLONG -c umf_free.c -o umf_l_free.o + $(C) -DDLONG -c umf_fsize.c -o umf_l_fsize.o + $(C) -DDLONG -c umf_is_permutation.c -o umf_l_is_permutation.o + $(C) -DDLONG -c umf_malloc.c -o umf_l_malloc.o + $(C) -DDLONG -c umf_realloc.c -o umf_l_realloc.o + $(C) -DDLONG -c umf_report_perm.c -o umf_l_report_perm.o + $(C) -DDLONG -c umf_singletons.c -o umf_l_singletons.o + $(C) -c umfpack_timer.c -o umfpack_gn_timer.o + $(C) -c umfpack_tictoc.c -o umfpack_gn_tictoc.o + $(C) -DDINT -DCONJUGATE_SOLVE -c umf_ltsolve.c -o umf_di_lhsolve.o + $(C) -DDINT -DCONJUGATE_SOLVE -c umf_utsolve.c -o umf_di_uhsolve.o + $(C) -DDINT -DDO_MAP -c umf_triplet.c -o umf_di_triplet_map_nox.o + $(C) -DDINT -DDO_VALUES -c umf_triplet.c -o umf_di_triplet_nomap_x.o + $(C) -DDINT -c umf_triplet.c -o umf_di_triplet_nomap_nox.o + $(C) -DDINT -DDO_MAP -DDO_VALUES -c umf_triplet.c -o umf_di_triplet_map_x.o + $(C) -DDINT -DFIXQ -c umf_assemble.c -o umf_di_assemble_fixq.o + $(C) -DDINT -DDROP -c umf_store_lu.c -o umf_di_store_lu_drop.o + $(C) -DDINT -c umf_assemble.c -o umf_di_assemble.o + $(C) -DDINT -c umf_blas3_update.c -o umf_di_blas3_update.o + $(C) -DDINT -c umf_build_tuples.c -o umf_di_build_tuples.o + $(C) -DDINT -c umf_create_element.c -o umf_di_create_element.o + $(C) -DDINT -c umf_dump.c -o umf_di_dump.o + $(C) -DDINT -c umf_extend_front.c -o umf_di_extend_front.o + $(C) -DDINT -c umf_garbage_collection.c -o umf_di_garbage_collection.o + $(C) -DDINT -c umf_get_memory.c -o umf_di_get_memory.o + $(C) -DDINT -c umf_init_front.c -o umf_di_init_front.o + $(C) -DDINT -c umf_kernel.c -o umf_di_kernel.o + $(C) -DDINT -c umf_kernel_init.c -o umf_di_kernel_init.o + $(C) -DDINT -c umf_kernel_wrapup.c -o umf_di_kernel_wrapup.o + $(C) -DDINT -c umf_local_search.c -o umf_di_local_search.o + $(C) -DDINT -c umf_lsolve.c -o umf_di_lsolve.o + $(C) -DDINT -c umf_ltsolve.c -o umf_di_ltsolve.o + $(C) -DDINT -c umf_mem_alloc_element.c -o umf_di_mem_alloc_element.o + $(C) -DDINT -c umf_mem_alloc_head_block.c -o umf_di_mem_alloc_head_block.o + $(C) -DDINT -c umf_mem_alloc_tail_block.c -o umf_di_mem_alloc_tail_block.o + $(C) -DDINT -c umf_mem_free_tail_block.c -o umf_di_mem_free_tail_block.o + $(C) -DDINT -c umf_mem_init_memoryspace.c -o umf_di_mem_init_memoryspace.o + $(C) -DDINT -c umf_report_vector.c -o umf_di_report_vector.o + $(C) -DDINT -c umf_row_search.c -o umf_di_row_search.o + $(C) -DDINT -c umf_scale_column.c -o umf_di_scale_column.o + $(C) -DDINT -c umf_set_stats.c -o umf_di_set_stats.o + $(C) -DDINT -c umf_solve.c -o umf_di_solve.o + $(C) -DDINT -c umf_symbolic_usage.c -o umf_di_symbolic_usage.o + $(C) -DDINT -c umf_transpose.c -o umf_di_transpose.o + $(C) -DDINT -c umf_tuple_lengths.c -o umf_di_tuple_lengths.o + $(C) -DDINT -c umf_usolve.c -o umf_di_usolve.o + $(C) -DDINT -c umf_utsolve.c -o umf_di_utsolve.o + $(C) -DDINT -c umf_valid_numeric.c -o umf_di_valid_numeric.o + $(C) -DDINT -c umf_valid_symbolic.c -o umf_di_valid_symbolic.o + $(C) -DDINT -c umf_grow_front.c -o umf_di_grow_front.o + $(C) -DDINT -c umf_start_front.c -o umf_di_start_front.o + $(C) -DDINT -c umf_2by2.c -o umf_di_2by2.o + $(C) -DDINT -c umf_store_lu.c -o umf_di_store_lu.o + $(C) -DDINT -c umf_scale.c -o umf_di_scale.o + $(C) -DDINT -DWSOLVE -c umfpack_solve.c -o umfpack_di_wsolve.o + $(C) -DDINT -c umfpack_col_to_triplet.c -o umfpack_di_col_to_triplet.o + $(C) -DDINT -c umfpack_defaults.c -o umfpack_di_defaults.o + $(C) -DDINT -c umfpack_free_numeric.c -o umfpack_di_free_numeric.o + $(C) -DDINT -c umfpack_free_symbolic.c -o umfpack_di_free_symbolic.o + $(C) -DDINT -c umfpack_get_numeric.c -o umfpack_di_get_numeric.o + $(C) -DDINT -c umfpack_get_lunz.c -o umfpack_di_get_lunz.o + $(C) -DDINT -c umfpack_get_symbolic.c -o umfpack_di_get_symbolic.o + $(C) -DDINT -c umfpack_get_determinant.c -o umfpack_di_get_determinant.o + $(C) -DDINT -c umfpack_numeric.c -o umfpack_di_numeric.o + $(C) -DDINT -c umfpack_qsymbolic.c -o umfpack_di_qsymbolic.o + $(C) -DDINT -c umfpack_report_control.c -o umfpack_di_report_control.o + $(C) -DDINT -c umfpack_report_info.c -o umfpack_di_report_info.o + $(C) -DDINT -c umfpack_report_matrix.c -o umfpack_di_report_matrix.o + $(C) -DDINT -c umfpack_report_numeric.c -o umfpack_di_report_numeric.o + $(C) -DDINT -c umfpack_report_perm.c -o umfpack_di_report_perm.o + $(C) -DDINT -c umfpack_report_status.c -o umfpack_di_report_status.o + $(C) -DDINT -c umfpack_report_symbolic.c -o umfpack_di_report_symbolic.o + $(C) -DDINT -c umfpack_report_triplet.c -o umfpack_di_report_triplet.o + $(C) -DDINT -c umfpack_report_vector.c -o umfpack_di_report_vector.o + $(C) -DDINT -c umfpack_solve.c -o umfpack_di_solve.o + $(C) -DDINT -c umfpack_symbolic.c -o umfpack_di_symbolic.o + $(C) -DDINT -c umfpack_transpose.c -o umfpack_di_transpose.o + $(C) -DDINT -c umfpack_triplet_to_col.c -o umfpack_di_triplet_to_col.o + $(C) -DDINT -c umfpack_scale.c -o umfpack_di_scale.o + $(C) -DDINT -c umfpack_load_numeric.c -o umfpack_di_load_numeric.o + $(C) -DDINT -c umfpack_save_numeric.c -o umfpack_di_save_numeric.o + $(C) -DDINT -c umfpack_load_symbolic.c -o umfpack_di_load_symbolic.o + $(C) -DDINT -c umfpack_save_symbolic.c -o umfpack_di_save_symbolic.o + $(C) -DDLONG -DCONJUGATE_SOLVE -c umf_ltsolve.c -o umf_dl_lhsolve.o + $(C) -DDLONG -DCONJUGATE_SOLVE -c umf_utsolve.c -o umf_dl_uhsolve.o + $(C) -DDLONG -DDO_MAP -c umf_triplet.c -o umf_dl_triplet_map_nox.o + $(C) -DDLONG -DDO_VALUES -c umf_triplet.c -o umf_dl_triplet_nomap_x.o + $(C) -DDLONG -c umf_triplet.c -o umf_dl_triplet_nomap_nox.o + $(C) -DDLONG -DDO_MAP -DDO_VALUES -c umf_triplet.c -o umf_dl_triplet_map_x.o + $(C) -DDLONG -DFIXQ -c umf_assemble.c -o umf_dl_assemble_fixq.o + $(C) -DDLONG -DDROP -c umf_store_lu.c -o umf_dl_store_lu_drop.o + $(C) -DDLONG -c umf_assemble.c -o umf_dl_assemble.o + $(C) -DDLONG -c umf_blas3_update.c -o umf_dl_blas3_update.o + $(C) -DDLONG -c umf_build_tuples.c -o umf_dl_build_tuples.o + $(C) -DDLONG -c umf_create_element.c -o umf_dl_create_element.o + $(C) -DDLONG -c umf_dump.c -o umf_dl_dump.o + $(C) -DDLONG -c umf_extend_front.c -o umf_dl_extend_front.o + $(C) -DDLONG -c umf_garbage_collection.c -o umf_dl_garbage_collection.o + $(C) -DDLONG -c umf_get_memory.c -o umf_dl_get_memory.o + $(C) -DDLONG -c umf_init_front.c -o umf_dl_init_front.o + $(C) -DDLONG -c umf_kernel.c -o umf_dl_kernel.o + $(C) -DDLONG -c umf_kernel_init.c -o umf_dl_kernel_init.o + $(C) -DDLONG -c umf_kernel_wrapup.c -o umf_dl_kernel_wrapup.o + $(C) -DDLONG -c umf_local_search.c -o umf_dl_local_search.o + $(C) -DDLONG -c umf_lsolve.c -o umf_dl_lsolve.o + $(C) -DDLONG -c umf_ltsolve.c -o umf_dl_ltsolve.o + $(C) -DDLONG -c umf_mem_alloc_element.c -o umf_dl_mem_alloc_element.o + $(C) -DDLONG -c umf_mem_alloc_head_block.c -o umf_dl_mem_alloc_head_block.o + $(C) -DDLONG -c umf_mem_alloc_tail_block.c -o umf_dl_mem_alloc_tail_block.o + $(C) -DDLONG -c umf_mem_free_tail_block.c -o umf_dl_mem_free_tail_block.o + $(C) -DDLONG -c umf_mem_init_memoryspace.c -o umf_dl_mem_init_memoryspace.o + $(C) -DDLONG -c umf_report_vector.c -o umf_dl_report_vector.o + $(C) -DDLONG -c umf_row_search.c -o umf_dl_row_search.o + $(C) -DDLONG -c umf_scale_column.c -o umf_dl_scale_column.o + $(C) -DDLONG -c umf_set_stats.c -o umf_dl_set_stats.o + $(C) -DDLONG -c umf_solve.c -o umf_dl_solve.o + $(C) -DDLONG -c umf_symbolic_usage.c -o umf_dl_symbolic_usage.o + $(C) -DDLONG -c umf_transpose.c -o umf_dl_transpose.o + $(C) -DDLONG -c umf_tuple_lengths.c -o umf_dl_tuple_lengths.o + $(C) -DDLONG -c umf_usolve.c -o umf_dl_usolve.o + $(C) -DDLONG -c umf_utsolve.c -o umf_dl_utsolve.o + $(C) -DDLONG -c umf_valid_numeric.c -o umf_dl_valid_numeric.o + $(C) -DDLONG -c umf_valid_symbolic.c -o umf_dl_valid_symbolic.o + $(C) -DDLONG -c umf_grow_front.c -o umf_dl_grow_front.o + $(C) -DDLONG -c umf_start_front.c -o umf_dl_start_front.o + $(C) -DDLONG -c umf_2by2.c -o umf_dl_2by2.o + $(C) -DDLONG -c umf_store_lu.c -o umf_dl_store_lu.o + $(C) -DDLONG -c umf_scale.c -o umf_dl_scale.o + $(C) -DDLONG -DWSOLVE -c umfpack_solve.c -o umfpack_dl_wsolve.o + $(C) -DDLONG -c umfpack_col_to_triplet.c -o umfpack_dl_col_to_triplet.o + $(C) -DDLONG -c umfpack_defaults.c -o umfpack_dl_defaults.o + $(C) -DDLONG -c umfpack_free_numeric.c -o umfpack_dl_free_numeric.o + $(C) -DDLONG -c umfpack_free_symbolic.c -o umfpack_dl_free_symbolic.o + $(C) -DDLONG -c umfpack_get_numeric.c -o umfpack_dl_get_numeric.o + $(C) -DDLONG -c umfpack_get_lunz.c -o umfpack_dl_get_lunz.o + $(C) -DDLONG -c umfpack_get_symbolic.c -o umfpack_dl_get_symbolic.o + $(C) -DDLONG -c umfpack_get_determinant.c -o umfpack_dl_get_determinant.o + $(C) -DDLONG -c umfpack_numeric.c -o umfpack_dl_numeric.o + $(C) -DDLONG -c umfpack_qsymbolic.c -o umfpack_dl_qsymbolic.o + $(C) -DDLONG -c umfpack_report_control.c -o umfpack_dl_report_control.o + $(C) -DDLONG -c umfpack_report_info.c -o umfpack_dl_report_info.o + $(C) -DDLONG -c umfpack_report_matrix.c -o umfpack_dl_report_matrix.o + $(C) -DDLONG -c umfpack_report_numeric.c -o umfpack_dl_report_numeric.o + $(C) -DDLONG -c umfpack_report_perm.c -o umfpack_dl_report_perm.o + $(C) -DDLONG -c umfpack_report_status.c -o umfpack_dl_report_status.o + $(C) -DDLONG -c umfpack_report_symbolic.c -o umfpack_dl_report_symbolic.o + $(C) -DDLONG -c umfpack_report_triplet.c -o umfpack_dl_report_triplet.o + $(C) -DDLONG -c umfpack_report_vector.c -o umfpack_dl_report_vector.o + $(C) -DDLONG -c umfpack_solve.c -o umfpack_dl_solve.o + $(C) -DDLONG -c umfpack_symbolic.c -o umfpack_dl_symbolic.o + $(C) -DDLONG -c umfpack_transpose.c -o umfpack_dl_transpose.o + $(C) -DDLONG -c umfpack_triplet_to_col.c -o umfpack_dl_triplet_to_col.o + $(C) -DDLONG -c umfpack_scale.c -o umfpack_dl_scale.o + $(C) -DDLONG -c umfpack_load_numeric.c -o umfpack_dl_load_numeric.o + $(C) -DDLONG -c umfpack_save_numeric.c -o umfpack_dl_save_numeric.o + $(C) -DDLONG -c umfpack_load_symbolic.c -o umfpack_dl_load_symbolic.o + $(C) -DDLONG -c umfpack_save_symbolic.c -o umfpack_dl_save_symbolic.o + $(C) -DZINT -DCONJUGATE_SOLVE -c umf_ltsolve.c -o umf_zi_lhsolve.o + $(C) -DZINT -DCONJUGATE_SOLVE -c umf_utsolve.c -o umf_zi_uhsolve.o + $(C) -DZINT -DDO_MAP -c umf_triplet.c -o umf_zi_triplet_map_nox.o + $(C) -DZINT -DDO_VALUES -c umf_triplet.c -o umf_zi_triplet_nomap_x.o + $(C) -DZINT -c umf_triplet.c -o umf_zi_triplet_nomap_nox.o + $(C) -DZINT -DDO_MAP -DDO_VALUES -c umf_triplet.c -o umf_zi_triplet_map_x.o + $(C) -DZINT -DFIXQ -c umf_assemble.c -o umf_zi_assemble_fixq.o + $(C) -DZINT -DDROP -c umf_store_lu.c -o umf_zi_store_lu_drop.o + $(C) -DZINT -c umf_assemble.c -o umf_zi_assemble.o + $(C) -DZINT -c umf_blas3_update.c -o umf_zi_blas3_update.o + $(C) -DZINT -c umf_build_tuples.c -o umf_zi_build_tuples.o + $(C) -DZINT -c umf_create_element.c -o umf_zi_create_element.o + $(C) -DZINT -c umf_dump.c -o umf_zi_dump.o + $(C) -DZINT -c umf_extend_front.c -o umf_zi_extend_front.o + $(C) -DZINT -c umf_garbage_collection.c -o umf_zi_garbage_collection.o + $(C) -DZINT -c umf_get_memory.c -o umf_zi_get_memory.o + $(C) -DZINT -c umf_init_front.c -o umf_zi_init_front.o + $(C) -DZINT -c umf_kernel.c -o umf_zi_kernel.o + $(C) -DZINT -c umf_kernel_init.c -o umf_zi_kernel_init.o + $(C) -DZINT -c umf_kernel_wrapup.c -o umf_zi_kernel_wrapup.o + $(C) -DZINT -c umf_local_search.c -o umf_zi_local_search.o + $(C) -DZINT -c umf_lsolve.c -o umf_zi_lsolve.o + $(C) -DZINT -c umf_ltsolve.c -o umf_zi_ltsolve.o + $(C) -DZINT -c umf_mem_alloc_element.c -o umf_zi_mem_alloc_element.o + $(C) -DZINT -c umf_mem_alloc_head_block.c -o umf_zi_mem_alloc_head_block.o + $(C) -DZINT -c umf_mem_alloc_tail_block.c -o umf_zi_mem_alloc_tail_block.o + $(C) -DZINT -c umf_mem_free_tail_block.c -o umf_zi_mem_free_tail_block.o + $(C) -DZINT -c umf_mem_init_memoryspace.c -o umf_zi_mem_init_memoryspace.o + $(C) -DZINT -c umf_report_vector.c -o umf_zi_report_vector.o + $(C) -DZINT -c umf_row_search.c -o umf_zi_row_search.o + $(C) -DZINT -c umf_scale_column.c -o umf_zi_scale_column.o + $(C) -DZINT -c umf_set_stats.c -o umf_zi_set_stats.o + $(C) -DZINT -c umf_solve.c -o umf_zi_solve.o + $(C) -DZINT -c umf_symbolic_usage.c -o umf_zi_symbolic_usage.o + $(C) -DZINT -c umf_transpose.c -o umf_zi_transpose.o + $(C) -DZINT -c umf_tuple_lengths.c -o umf_zi_tuple_lengths.o + $(C) -DZINT -c umf_usolve.c -o umf_zi_usolve.o + $(C) -DZINT -c umf_utsolve.c -o umf_zi_utsolve.o + $(C) -DZINT -c umf_valid_numeric.c -o umf_zi_valid_numeric.o + $(C) -DZINT -c umf_valid_symbolic.c -o umf_zi_valid_symbolic.o + $(C) -DZINT -c umf_grow_front.c -o umf_zi_grow_front.o + $(C) -DZINT -c umf_start_front.c -o umf_zi_start_front.o + $(C) -DZINT -c umf_2by2.c -o umf_zi_2by2.o + $(C) -DZINT -c umf_store_lu.c -o umf_zi_store_lu.o + $(C) -DZINT -c umf_scale.c -o umf_zi_scale.o + $(C) -DZINT -DWSOLVE -c umfpack_solve.c -o umfpack_zi_wsolve.o + $(C) -DZINT -c umfpack_col_to_triplet.c -o umfpack_zi_col_to_triplet.o + $(C) -DZINT -c umfpack_defaults.c -o umfpack_zi_defaults.o + $(C) -DZINT -c umfpack_free_numeric.c -o umfpack_zi_free_numeric.o + $(C) -DZINT -c umfpack_free_symbolic.c -o umfpack_zi_free_symbolic.o + $(C) -DZINT -c umfpack_get_numeric.c -o umfpack_zi_get_numeric.o + $(C) -DZINT -c umfpack_get_lunz.c -o umfpack_zi_get_lunz.o + $(C) -DZINT -c umfpack_get_symbolic.c -o umfpack_zi_get_symbolic.o + $(C) -DZINT -c umfpack_get_determinant.c -o umfpack_zi_get_determinant.o + $(C) -DZINT -c umfpack_numeric.c -o umfpack_zi_numeric.o + $(C) -DZINT -c umfpack_qsymbolic.c -o umfpack_zi_qsymbolic.o + $(C) -DZINT -c umfpack_report_control.c -o umfpack_zi_report_control.o + $(C) -DZINT -c umfpack_report_info.c -o umfpack_zi_report_info.o + $(C) -DZINT -c umfpack_report_matrix.c -o umfpack_zi_report_matrix.o + $(C) -DZINT -c umfpack_report_numeric.c -o umfpack_zi_report_numeric.o + $(C) -DZINT -c umfpack_report_perm.c -o umfpack_zi_report_perm.o + $(C) -DZINT -c umfpack_report_status.c -o umfpack_zi_report_status.o + $(C) -DZINT -c umfpack_report_symbolic.c -o umfpack_zi_report_symbolic.o + $(C) -DZINT -c umfpack_report_triplet.c -o umfpack_zi_report_triplet.o + $(C) -DZINT -c umfpack_report_vector.c -o umfpack_zi_report_vector.o + $(C) -DZINT -c umfpack_solve.c -o umfpack_zi_solve.o + $(C) -DZINT -c umfpack_symbolic.c -o umfpack_zi_symbolic.o + $(C) -DZINT -c umfpack_transpose.c -o umfpack_zi_transpose.o + $(C) -DZINT -c umfpack_triplet_to_col.c -o umfpack_zi_triplet_to_col.o + $(C) -DZINT -c umfpack_scale.c -o umfpack_zi_scale.o + $(C) -DZINT -c umfpack_load_numeric.c -o umfpack_zi_load_numeric.o + $(C) -DZINT -c umfpack_save_numeric.c -o umfpack_zi_save_numeric.o + $(C) -DZINT -c umfpack_load_symbolic.c -o umfpack_zi_load_symbolic.o + $(C) -DZINT -c umfpack_save_symbolic.c -o umfpack_zi_save_symbolic.o + $(C) -DZLONG -DCONJUGATE_SOLVE -c umf_ltsolve.c -o umf_zl_lhsolve.o + $(C) -DZLONG -DCONJUGATE_SOLVE -c umf_utsolve.c -o umf_zl_uhsolve.o + $(C) -DZLONG -DDO_MAP -c umf_triplet.c -o umf_zl_triplet_map_nox.o + $(C) -DZLONG -DDO_VALUES -c umf_triplet.c -o umf_zl_triplet_nomap_x.o + $(C) -DZLONG -c umf_triplet.c -o umf_zl_triplet_nomap_nox.o + $(C) -DZLONG -DDO_MAP -DDO_VALUES -c umf_triplet.c -o umf_zl_triplet_map_x.o + $(C) -DZLONG -DFIXQ -c umf_assemble.c -o umf_zl_assemble_fixq.o + $(C) -DZLONG -DDROP -c umf_store_lu.c -o umf_zl_store_lu_drop.o + $(C) -DZLONG -c umf_assemble.c -o umf_zl_assemble.o + $(C) -DZLONG -c umf_blas3_update.c -o umf_zl_blas3_update.o + $(C) -DZLONG -c umf_build_tuples.c -o umf_zl_build_tuples.o + $(C) -DZLONG -c umf_create_element.c -o umf_zl_create_element.o + $(C) -DZLONG -c umf_dump.c -o umf_zl_dump.o + $(C) -DZLONG -c umf_extend_front.c -o umf_zl_extend_front.o + $(C) -DZLONG -c umf_garbage_collection.c -o umf_zl_garbage_collection.o + $(C) -DZLONG -c umf_get_memory.c -o umf_zl_get_memory.o + $(C) -DZLONG -c umf_init_front.c -o umf_zl_init_front.o + $(C) -DZLONG -c umf_kernel.c -o umf_zl_kernel.o + $(C) -DZLONG -c umf_kernel_init.c -o umf_zl_kernel_init.o + $(C) -DZLONG -c umf_kernel_wrapup.c -o umf_zl_kernel_wrapup.o + $(C) -DZLONG -c umf_local_search.c -o umf_zl_local_search.o + $(C) -DZLONG -c umf_lsolve.c -o umf_zl_lsolve.o + $(C) -DZLONG -c umf_ltsolve.c -o umf_zl_ltsolve.o + $(C) -DZLONG -c umf_mem_alloc_element.c -o umf_zl_mem_alloc_element.o + $(C) -DZLONG -c umf_mem_alloc_head_block.c -o umf_zl_mem_alloc_head_block.o + $(C) -DZLONG -c umf_mem_alloc_tail_block.c -o umf_zl_mem_alloc_tail_block.o + $(C) -DZLONG -c umf_mem_free_tail_block.c -o umf_zl_mem_free_tail_block.o + $(C) -DZLONG -c umf_mem_init_memoryspace.c -o umf_zl_mem_init_memoryspace.o + $(C) -DZLONG -c umf_report_vector.c -o umf_zl_report_vector.o + $(C) -DZLONG -c umf_row_search.c -o umf_zl_row_search.o + $(C) -DZLONG -c umf_scale_column.c -o umf_zl_scale_column.o + $(C) -DZLONG -c umf_set_stats.c -o umf_zl_set_stats.o + $(C) -DZLONG -c umf_solve.c -o umf_zl_solve.o + $(C) -DZLONG -c umf_symbolic_usage.c -o umf_zl_symbolic_usage.o + $(C) -DZLONG -c umf_transpose.c -o umf_zl_transpose.o + $(C) -DZLONG -c umf_tuple_lengths.c -o umf_zl_tuple_lengths.o + $(C) -DZLONG -c umf_usolve.c -o umf_zl_usolve.o + $(C) -DZLONG -c umf_utsolve.c -o umf_zl_utsolve.o + $(C) -DZLONG -c umf_valid_numeric.c -o umf_zl_valid_numeric.o + $(C) -DZLONG -c umf_valid_symbolic.c -o umf_zl_valid_symbolic.o + $(C) -DZLONG -c umf_grow_front.c -o umf_zl_grow_front.o + $(C) -DZLONG -c umf_start_front.c -o umf_zl_start_front.o + $(C) -DZLONG -c umf_2by2.c -o umf_zl_2by2.o + $(C) -DZLONG -c umf_store_lu.c -o umf_zl_store_lu.o + $(C) -DZLONG -c umf_scale.c -o umf_zl_scale.o + $(C) -DZLONG -DWSOLVE -c umfpack_solve.c -o umfpack_zl_wsolve.o + $(C) -DZLONG -c umfpack_col_to_triplet.c -o umfpack_zl_col_to_triplet.o + $(C) -DZLONG -c umfpack_defaults.c -o umfpack_zl_defaults.o + $(C) -DZLONG -c umfpack_free_numeric.c -o umfpack_zl_free_numeric.o + $(C) -DZLONG -c umfpack_free_symbolic.c -o umfpack_zl_free_symbolic.o + $(C) -DZLONG -c umfpack_get_numeric.c -o umfpack_zl_get_numeric.o + $(C) -DZLONG -c umfpack_get_lunz.c -o umfpack_zl_get_lunz.o + $(C) -DZLONG -c umfpack_get_symbolic.c -o umfpack_zl_get_symbolic.o + $(C) -DZLONG -c umfpack_get_determinant.c -o umfpack_zl_get_determinant.o + $(C) -DZLONG -c umfpack_numeric.c -o umfpack_zl_numeric.o + $(C) -DZLONG -c umfpack_qsymbolic.c -o umfpack_zl_qsymbolic.o + $(C) -DZLONG -c umfpack_report_control.c -o umfpack_zl_report_control.o + $(C) -DZLONG -c umfpack_report_info.c -o umfpack_zl_report_info.o + $(C) -DZLONG -c umfpack_report_matrix.c -o umfpack_zl_report_matrix.o + $(C) -DZLONG -c umfpack_report_numeric.c -o umfpack_zl_report_numeric.o + $(C) -DZLONG -c umfpack_report_perm.c -o umfpack_zl_report_perm.o + $(C) -DZLONG -c umfpack_report_status.c -o umfpack_zl_report_status.o + $(C) -DZLONG -c umfpack_report_symbolic.c -o umfpack_zl_report_symbolic.o + $(C) -DZLONG -c umfpack_report_triplet.c -o umfpack_zl_report_triplet.o + $(C) -DZLONG -c umfpack_report_vector.c -o umfpack_zl_report_vector.o + $(C) -DZLONG -c umfpack_solve.c -o umfpack_zl_solve.o + $(C) -DZLONG -c umfpack_symbolic.c -o umfpack_zl_symbolic.o + $(C) -DZLONG -c umfpack_transpose.c -o umfpack_zl_transpose.o + $(C) -DZLONG -c umfpack_triplet_to_col.c -o umfpack_zl_triplet_to_col.o + $(C) -DZLONG -c umfpack_scale.c -o umfpack_zl_scale.o + $(C) -DZLONG -c umfpack_load_numeric.c -o umfpack_zl_load_numeric.o + $(C) -DZLONG -c umfpack_save_numeric.c -o umfpack_zl_save_numeric.o + $(C) -DZLONG -c umfpack_load_symbolic.c -o umfpack_zl_load_symbolic.o + $(C) -DZLONG -c umfpack_save_symbolic.c -o umfpack_zl_save_symbolic.o + $(AR) cr ../Lib/libumfpack.a \ + umf_i_analyze.o umf_i_apply_order.o umf_i_colamd.o umf_i_free.o \ + umf_i_fsize.o umf_i_is_permutation.o umf_i_malloc.o umf_i_realloc.o \ + umf_i_report_perm.o umf_i_singletons.o \ + umf_l_analyze.o umf_l_apply_order.o umf_l_colamd.o umf_l_free.o \ + umf_l_fsize.o umf_l_is_permutation.o umf_l_malloc.o umf_l_realloc.o \ + umf_l_report_perm.o umf_l_singletons.o \ + umfpack_gn_timer.o umfpack_gn_tictoc.o \ + umf_di_lhsolve.o \ + umf_di_uhsolve.o umf_di_triplet_map_nox.o umf_di_triplet_nomap_x.o \ + umf_di_triplet_nomap_nox.o umf_di_triplet_map_x.o \ + umf_di_assemble_fixq.o umf_di_store_lu_drop.o umf_di_assemble.o \ + umf_di_blas3_update.o umf_di_build_tuples.o \ + umf_di_create_element.o umf_di_dump.o umf_di_extend_front.o \ + umf_di_garbage_collection.o umf_di_get_memory.o \ + umf_di_init_front.o umf_di_kernel.o umf_di_kernel_init.o \ + umf_di_kernel_wrapup.o umf_di_local_search.o umf_di_lsolve.o \ + umf_di_ltsolve.o umf_di_mem_alloc_element.o \ + umf_di_mem_alloc_head_block.o umf_di_mem_alloc_tail_block.o \ + umf_di_mem_free_tail_block.o umf_di_mem_init_memoryspace.o \ + umf_di_report_vector.o umf_di_row_search.o umf_di_scale_column.o \ + umf_di_set_stats.o umf_di_solve.o umf_di_symbolic_usage.o \ + umf_di_transpose.o umf_di_tuple_lengths.o umf_di_usolve.o \ + umf_di_utsolve.o umf_di_valid_numeric.o umf_di_valid_symbolic.o \ + umf_di_grow_front.o umf_di_start_front.o umf_di_2by2.o \ + umf_di_store_lu.o umf_di_scale.o umfpack_di_wsolve.o \ + umfpack_di_col_to_triplet.o umfpack_di_defaults.o \ + umfpack_di_free_numeric.o umfpack_di_free_symbolic.o \ + umfpack_di_get_numeric.o umfpack_di_get_lunz.o \ + umfpack_di_get_symbolic.o umfpack_di_get_determinant.o \ + umfpack_di_numeric.o \ + umfpack_di_qsymbolic.o umfpack_di_report_control.o \ + umfpack_di_report_info.o umfpack_di_report_matrix.o \ + umfpack_di_report_numeric.o umfpack_di_report_perm.o \ + umfpack_di_report_status.o umfpack_di_report_symbolic.o \ + umfpack_di_report_triplet.o umfpack_di_report_vector.o \ + umfpack_di_solve.o umfpack_di_symbolic.o umfpack_di_transpose.o \ + umfpack_di_triplet_to_col.o umfpack_di_scale.o \ + umfpack_di_load_numeric.o umfpack_di_save_numeric.o \ + umfpack_di_load_symbolic.o umfpack_di_save_symbolic.o \ + umf_dl_lhsolve.o \ + umf_dl_uhsolve.o umf_dl_triplet_map_nox.o umf_dl_triplet_nomap_x.o \ + umf_dl_triplet_nomap_nox.o umf_dl_triplet_map_x.o \ + umf_dl_assemble_fixq.o umf_dl_store_lu_drop.o umf_dl_assemble.o \ + umf_dl_blas3_update.o umf_dl_build_tuples.o \ + umf_dl_create_element.o umf_dl_dump.o umf_dl_extend_front.o \ + umf_dl_garbage_collection.o umf_dl_get_memory.o \ + umf_dl_init_front.o umf_dl_kernel.o umf_dl_kernel_init.o \ + umf_dl_kernel_wrapup.o umf_dl_local_search.o umf_dl_lsolve.o \ + umf_dl_ltsolve.o umf_dl_mem_alloc_element.o \ + umf_dl_mem_alloc_head_block.o umf_dl_mem_alloc_tail_block.o \ + umf_dl_mem_free_tail_block.o umf_dl_mem_init_memoryspace.o \ + umf_dl_report_vector.o umf_dl_row_search.o umf_dl_scale_column.o \ + umf_dl_set_stats.o umf_dl_solve.o umf_dl_symbolic_usage.o \ + umf_dl_transpose.o umf_dl_tuple_lengths.o umf_dl_usolve.o \ + umf_dl_utsolve.o umf_dl_valid_numeric.o umf_dl_valid_symbolic.o \ + umf_dl_grow_front.o umf_dl_start_front.o umf_dl_2by2.o \ + umf_dl_store_lu.o umf_dl_scale.o umfpack_dl_wsolve.o \ + umfpack_dl_col_to_triplet.o umfpack_dl_defaults.o \ + umfpack_dl_free_numeric.o umfpack_dl_free_symbolic.o \ + umfpack_dl_get_numeric.o umfpack_dl_get_lunz.o \ + umfpack_dl_get_symbolic.o umfpack_dl_get_determinant.o \ + umfpack_dl_numeric.o \ + umfpack_dl_qsymbolic.o umfpack_dl_report_control.o \ + umfpack_dl_report_info.o umfpack_dl_report_matrix.o \ + umfpack_dl_report_numeric.o umfpack_dl_report_perm.o \ + umfpack_dl_report_status.o umfpack_dl_report_symbolic.o \ + umfpack_dl_report_triplet.o umfpack_dl_report_vector.o \ + umfpack_dl_solve.o umfpack_dl_symbolic.o umfpack_dl_transpose.o \ + umfpack_dl_triplet_to_col.o umfpack_dl_scale.o \ + umfpack_dl_load_numeric.o umfpack_dl_save_numeric.o \ + umfpack_dl_load_symbolic.o umfpack_dl_save_symbolic.o \ + umf_zi_lhsolve.o \ + umf_zi_uhsolve.o umf_zi_triplet_map_nox.o umf_zi_triplet_nomap_x.o \ + umf_zi_triplet_nomap_nox.o umf_zi_triplet_map_x.o \ + umf_zi_assemble_fixq.o umf_zi_store_lu_drop.o umf_zi_assemble.o \ + umf_zi_blas3_update.o umf_zi_build_tuples.o \ + umf_zi_create_element.o umf_zi_dump.o umf_zi_extend_front.o \ + umf_zi_garbage_collection.o umf_zi_get_memory.o \ + umf_zi_init_front.o umf_zi_kernel.o umf_zi_kernel_init.o \ + umf_zi_kernel_wrapup.o umf_zi_local_search.o umf_zi_lsolve.o \ + umf_zi_ltsolve.o umf_zi_mem_alloc_element.o \ + umf_zi_mem_alloc_head_block.o umf_zi_mem_alloc_tail_block.o \ + umf_zi_mem_free_tail_block.o umf_zi_mem_init_memoryspace.o \ + umf_zi_report_vector.o umf_zi_row_search.o umf_zi_scale_column.o \ + umf_zi_set_stats.o umf_zi_solve.o umf_zi_symbolic_usage.o \ + umf_zi_transpose.o umf_zi_tuple_lengths.o umf_zi_usolve.o \ + umf_zi_utsolve.o umf_zi_valid_numeric.o umf_zi_valid_symbolic.o \ + umf_zi_grow_front.o umf_zi_start_front.o umf_zi_2by2.o \ + umf_zi_store_lu.o umf_zi_scale.o umfpack_zi_wsolve.o \ + umfpack_zi_col_to_triplet.o umfpack_zi_defaults.o \ + umfpack_zi_free_numeric.o umfpack_zi_free_symbolic.o \ + umfpack_zi_get_numeric.o umfpack_zi_get_lunz.o \ + umfpack_zi_get_symbolic.o umfpack_zi_get_determinant.o \ + umfpack_zi_numeric.o \ + umfpack_zi_qsymbolic.o umfpack_zi_report_control.o \ + umfpack_zi_report_info.o umfpack_zi_report_matrix.o \ + umfpack_zi_report_numeric.o umfpack_zi_report_perm.o \ + umfpack_zi_report_status.o umfpack_zi_report_symbolic.o \ + umfpack_zi_report_triplet.o umfpack_zi_report_vector.o \ + umfpack_zi_solve.o umfpack_zi_symbolic.o umfpack_zi_transpose.o \ + umfpack_zi_triplet_to_col.o umfpack_zi_scale.o \ + umfpack_zi_load_numeric.o umfpack_zi_save_numeric.o \ + umfpack_zi_load_symbolic.o umfpack_zi_save_symbolic.o \ + umf_zl_lhsolve.o \ + umf_zl_uhsolve.o umf_zl_triplet_map_nox.o umf_zl_triplet_nomap_x.o \ + umf_zl_triplet_nomap_nox.o umf_zl_triplet_map_x.o \ + umf_zl_assemble_fixq.o umf_zl_store_lu_drop.o umf_zl_assemble.o \ + umf_zl_blas3_update.o umf_zl_build_tuples.o \ + umf_zl_create_element.o umf_zl_dump.o umf_zl_extend_front.o \ + umf_zl_garbage_collection.o umf_zl_get_memory.o \ + umf_zl_init_front.o umf_zl_kernel.o umf_zl_kernel_init.o \ + umf_zl_kernel_wrapup.o umf_zl_local_search.o umf_zl_lsolve.o \ + umf_zl_ltsolve.o umf_zl_mem_alloc_element.o \ + umf_zl_mem_alloc_head_block.o umf_zl_mem_alloc_tail_block.o \ + umf_zl_mem_free_tail_block.o umf_zl_mem_init_memoryspace.o \ + umf_zl_report_vector.o umf_zl_row_search.o umf_zl_scale_column.o \ + umf_zl_set_stats.o umf_zl_solve.o umf_zl_symbolic_usage.o \ + umf_zl_transpose.o umf_zl_tuple_lengths.o umf_zl_usolve.o \ + umf_zl_utsolve.o umf_zl_valid_numeric.o umf_zl_valid_symbolic.o \ + umf_zl_grow_front.o umf_zl_start_front.o umf_zl_2by2.o \ + umf_zl_store_lu.o umf_zl_scale.o umfpack_zl_wsolve.o \ + umfpack_zl_col_to_triplet.o umfpack_zl_defaults.o \ + umfpack_zl_free_numeric.o umfpack_zl_free_symbolic.o \ + umfpack_zl_get_numeric.o umfpack_zl_get_lunz.o \ + umfpack_zl_get_symbolic.o umfpack_zl_get_determinant.o \ + umfpack_zl_numeric.o \ + umfpack_zl_qsymbolic.o umfpack_zl_report_control.o \ + umfpack_zl_report_info.o umfpack_zl_report_matrix.o \ + umfpack_zl_report_numeric.o umfpack_zl_report_perm.o \ + umfpack_zl_report_status.o umfpack_zl_report_symbolic.o \ + umfpack_zl_report_triplet.o umfpack_zl_report_vector.o \ + umfpack_zl_solve.o umfpack_zl_symbolic.o umfpack_zl_transpose.o \ + umfpack_zl_triplet_to_col.o umfpack_zl_scale.o \ + umfpack_zl_load_numeric.o umfpack_zl_save_numeric.o \ + umfpack_zl_load_symbolic.o umfpack_zl_save_symbolic.o + - $(RANLIB) ../Lib/libumfpack.a + +#------------------------------------------------------------------------------- +# Remove all but the files in the original distribution +#------------------------------------------------------------------------------- + +purge: clean + - $(RM) ../Lib/libumfpack.a diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.c b/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.c @@ -0,0 +1,859 @@ +/* ========================================================================== */ +/* === UMF_2by2 ============================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Not user-callable. Computes a row permutation P so that A (P,:) has a + * mostly zero-free diagonal, with large entries on the diagonal. It does this + * by swapping pairs of rows. Once a row is swapped it is not swapped again. + * This is a "cheap" assignment, not a complete max. transversal or + * bi-partite matching. It is only a partial matching. For most matrices + * for which this algorithm is used, however, the matching is complete (in + * UMFPACK this algorithm is used for matrices with roughly symmetric pattern, + * and these matrices typically have a mostly-zero-free diagonal to begin with. + * This algorithm is not meant to be used on arbitrary unsymmetric matrices + * (for those matrices, UMFPACK uses its unsymmetric strategy and does not + * use this algorithm). + * + * Even if incomplete, the matching is usually good enough for UMFPACK's + * symmetric strategy, which can easily pivot off the diagonal during numerical + * factorization if it finds a weak diagonal entry. + * + * The algorithms works as follows. First, row scaling factors are computed, + * and weak diagonal entries are found. A weak entry is a value A(k,k) whose + * absolute value is < tol * max (abs (A (:,k))). For each weak diagonal k in + * increasing order of degree in A+A', the algorithm finds an index j such + * that A (k,j) and A (j,k) are "large" (greater than or equal to tol times + * the largest magnitude in their columns). Row j must also not have already + * been swapped. Rows j and k are then swapped. If we come to a diagonal k + * that has already been swapped, then it is not modified. This case occurs + * for "oxo" pivots: + * + * k j + * k o x + * j x o + * + * which are swapped once to obtain + * + * k j + * j x o + * k o x + * + * These two rows are then not modified any further (A (j,j) was weak, but + * after one swap the permuted the jth diagonal entry is strong. + * + * This algorithm only works on square matrices (real, complex, or pattern- + * only). The numerical values are optional. If not present, each entry is + * treated as numerically acceptable (tol is ignored), and the algorithm + * operates by just using the pattern, not the values. Each column of the + * input matrix A must be sorted, with no duplicate entries. The matrix A + * can be optionally scaled prior to the numerical test. The matrix A (:,P) + * has the same diagonal entries as A (:,P), except in different order. So + * the output permutation P can also be used to swap the columns of A. + */ + +#include "umf_internal.h" + +#ifndef NDEBUG +#include "umf_is_permutation.h" +#endif + +/* x is "weak" if it is less than ctol. If x or ctol are NaN, then define + * x as not "weak". This is a rather arbitrary choice, made to simplify the + * computation. On all but a PC with Microsoft C/C++, this test becomes + * ((x) - ctol < 0). */ +#define WEAK(x,ctol) (SCALAR_IS_LTZERO ((x)-(ctol))) + +/* For flag value in Next [col] */ +#define IS_WEAK -2 + +/* ========================================================================== */ +/* === two_by_two =========================================================== */ +/* ========================================================================== */ + +PRIVATE Int two_by_two /* returns # unmatched weak diagonals */ +( + /* input, not modified */ + Int n2, /* C is n2-by-n2 */ + Int Cp [ ], /* size n2+1, column pointers for C */ + Int Ci [ ], /* size snz = Cp [n2], row indices for C */ + Int Degree [ ], /* Degree [i] = degree of row i of C+C' */ + + /* input, not defined on output */ + Int Next [ ], /* Next [k] == IS_WEAK if k is a weak diagonal */ + Int Ri [ ], /* Ri [i] is the length of row i in C */ + + /* output, not defined on input */ + Int P [ ], + + /* workspace, not defined on input or output */ + Int Rp [ ], + Int Head [ ] +) +{ + Int deg, newcol, row, col, p, p2, unmatched, k, j, j2, j_best, best, jdiff, + jdiff_best, jdeg, jdeg_best, cp, cp1, cp2, rp, rp1, rp2, maxdeg, + mindeg ; + + /* ---------------------------------------------------------------------- */ + /* place weak diagonals in the degree lists */ + /* ---------------------------------------------------------------------- */ + + for (deg = 0 ; deg < n2 ; deg++) + { + Head [deg] = EMPTY ; + } + + maxdeg = 0 ; + mindeg = Int_MAX ; + for (newcol = n2-1 ; newcol >= 0 ; newcol--) + { + if (Next [newcol] == IS_WEAK) + { + /* add this column to the list of weak nodes */ + DEBUGm1 ((" newcol "ID" has a weak diagonal deg "ID"\n", + newcol, deg)) ; + deg = Degree [newcol] ; + ASSERT (deg >= 0 && deg < n2) ; + Next [newcol] = Head [deg] ; + Head [deg] = newcol ; + maxdeg = MAX (maxdeg, deg) ; + mindeg = MIN (mindeg, deg) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* construct R = C' (C = strong entries in pruned submatrix) */ + /* ---------------------------------------------------------------------- */ + + /* Ri [0..n2-1] is the length of each row of R */ + /* use P as temporary pointer into the row form of R [ */ + Rp [0] = 0 ; + for (row = 0 ; row < n2 ; row++) + { + Rp [row+1] = Rp [row] + Ri [row] ; + P [row] = Rp [row] ; + } + /* Ri no longer needed for row counts */ + + /* all entries in C are strong */ + for (col = 0 ; col < n2 ; col++) + { + p2 = Cp [col+1] ; + for (p = Cp [col] ; p < p2 ; p++) + { + /* place the column index in row = Ci [p] */ + Ri [P [Ci [p]]++] = col ; + } + } + + /* contents of P no longer needed ] */ + +#ifndef NDEBUG + DEBUG0 (("==================R: row form of strong entries in A:\n")) ; + UMF_dump_col_matrix ((double *) NULL, +#ifdef COMPLEX + (double *) NULL, +#endif + Ri, Rp, n2, n2, Rp [n2]) ; +#endif + ASSERT (AMD_valid (n2, n2, Rp, Ri)) ; + + /* ---------------------------------------------------------------------- */ + /* for each weak diagonal, find a pair of strong off-diagonal entries */ + /* ---------------------------------------------------------------------- */ + + for (row = 0 ; row < n2 ; row++) + { + P [row] = EMPTY ; + } + + unmatched = 0 ; + best = EMPTY ; + jdiff = EMPTY ; + jdeg = EMPTY ; + + for (deg = mindeg ; deg <= maxdeg ; deg++) + { + /* find the next weak diagonal of lowest degree */ + DEBUGm2 (("---------------------------------- Deg: "ID"\n", deg)) ; + for (k = Head [deg] ; k != EMPTY ; k = Next [k]) + { + DEBUGm2 (("k: "ID"\n", k)) ; + if (P [k] == EMPTY) + { + /* C (k,k) is a weak diagonal entry. Find an index j != k such + * that C (j,k) and C (k,j) are both strong, and also such + * that Degree [j] is minimized. In case of a tie, pick + * the smallest index j. C and R contain the pattern of + * strong entries only. + * + * Note that row k of R and column k of C are both sorted. */ + + DEBUGm4 (("===== Weak diagonal k = "ID"\n", k)) ; + DEBUG1 (("Column k of C:\n")) ; + for (p = Cp [k] ; p < Cp [k+1] ; p++) + { + DEBUG1 ((" "ID": deg "ID"\n", Ci [p], Degree [Ci [p]])); + } + DEBUG1 (("Row k of R (strong entries only):\n")) ; + for (p = Rp [k] ; p < Rp [k+1] ; p++) + { + DEBUG1 ((" "ID": deg "ID"\n", Ri [p], Degree [Ri [p]])); + } + + /* no (C (k,j), C (j,k)) pair exists yet */ + j_best = EMPTY ; + jdiff_best = Int_MAX ; + jdeg_best = Int_MAX ; + + /* pointers into column k (including values) */ + cp1 = Cp [k] ; + cp2 = Cp [k+1] ; + cp = cp1 ; + + /* pointers into row k (strong entries only, no values) */ + rp1 = Rp [k] ; + rp2 = Rp [k+1] ; + rp = rp1 ; + + /* while entries searched in column k and row k */ + while (TRUE) + { + + if (cp >= cp2) + { + /* no more entries in this column */ + break ; + } + + /* get C (j,k), which is strong */ + j = Ci [cp] ; + + if (rp >= rp2) + { + /* no more entries in this column */ + break ; + } + + /* get R (k,j2), which is strong */ + j2 = Ri [rp] ; + + if (j < j2) + { + /* C (j,k) is strong, but R (k,j) is not strong */ + cp++ ; + continue ; + } + + if (j2 < j) + { + /* C (k,j2) is strong, but R (j2,k) is not strong */ + rp++ ; + continue ; + } + + /* j == j2: C (j,k) is strong and R (k,j) is strong */ + + best = FALSE ; + + if (P [j] == EMPTY) + { + /* j has not yet been matched */ + jdeg = Degree [j] ; + jdiff = SCALAR_ABS (k-j) ; + + DEBUG1 (("Try candidate j "ID" deg "ID" diff "ID + "\n", j, jdeg, jdiff)) ; + + if (j_best == EMPTY) + { + /* this is the first candidate seen */ + DEBUG1 ((" first\n")) ; + best = TRUE ; + } + else + { + if (jdeg < jdeg_best) + { + /* the degree of j is best seen so far. */ + DEBUG1 ((" least degree\n")) ; + best = TRUE ; + } + else if (jdeg == jdeg_best) + { + /* degree of j and j_best are the same */ + /* tie break by nearest node number */ + if (jdiff < jdiff_best) + { + DEBUG1 ((" tie degree, closer\n")) ; + best = TRUE ; + } + else if (jdiff == jdiff_best) + { + /* |j-k| = |j_best-k|. For any given k + * and j_best there is only one other j + * than can be just as close as j_best. + * Tie break by picking the smaller of + * j and j_best */ + DEBUG1 ((" tie degree, as close\n")); + best = j < j_best ; + } + } + else + { + /* j has higher degree than best so far */ + best = FALSE ; + } + } + } + + if (best) + { + /* j is best match for k */ + /* found a strong pair, A (j,k) and A (k,j) */ + DEBUG1 ((" --- Found pair k: "ID" j: " ID + " jdeg: "ID" jdiff: "ID"\n", + k, j, jdeg, jdiff)) ; + ASSERT (jdiff != EMPTY) ; + ASSERT (jdeg != EMPTY) ; + j_best = j ; + jdeg_best = jdeg ; + jdiff_best = jdiff ; + } + + /* get the next entries in column k and row k */ + cp++ ; + rp++ ; + } + + /* save the pair (j,k), if we found one */ + if (j_best != EMPTY) + { + j = j_best ; + DEBUGm4 ((" --- best pair j: "ID" for k: "ID"\n", j, k)) ; + P [k] = j ; + P [j] = k ; + } + else + { + /* no match was found for k */ + unmatched++ ; + } + } + } + } + + /* ---------------------------------------------------------------------- */ + /* finalize the row permutation, P */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n2 ; k++) + { + if (P [k] == EMPTY) + { + P [k] = k ; + } + } + ASSERT (UMF_is_permutation (P, Rp, n2, n2)) ; + + return (unmatched) ; +} + + +/* ========================================================================== */ +/* === UMF_2by2 ============================================================= */ +/* ========================================================================== */ + +GLOBAL void UMF_2by2 +( + /* input, not modified: */ + Int n, /* A is n-by-n */ + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + const double Ax [ ], /* size nz if present */ +#ifdef COMPLEX + const double Az [ ], /* size nz if present */ +#endif + double tol, /* tolerance for determining whether or not an + * entry is numerically acceptable. If tol <= 0 + * then all numerical values ignored. */ + Int scale, /* scaling to perform (none, sum, or max) */ + Int Cperm1 [ ], /* singleton permutations */ +#ifndef NDEBUG + Int Rperm1 [ ], /* not needed, since Rperm1 = Cperm1 for submatrix S */ +#endif + Int InvRperm1 [ ], /* inverse of Rperm1 */ + Int n1, /* number of singletons */ + Int nempty, /* number of empty rows/cols */ + + /* input, contents undefined on output: */ + Int Degree [ ], /* Degree [j] is the number of off-diagonal + * entries in row/column j of S+S', where + * where S = A (Cperm1 [n1..], Rperm1 [n1..]). + * Note that S is not used, nor formed. */ + + /* output: */ + Int P [ ], /* P [k] = i means original row i is kth row in S(P,:) + * where S = A (Cperm1 [n1..], Rperm1 [n1..]) */ + Int *p_nweak, + Int *p_unmatched, + + /* workspace (not defined on input or output): */ + Int Ri [ ], /* of size >= max (nz, n) */ + Int Rp [ ], /* of size n+1 */ + double Rs [ ], /* of size n if present. Rs = sum (abs (A),2) or + * max (abs (A),2), the sum or max of each row. Unused + * if scale is equal to UMFPACK_SCALE_NONE. */ + Int Head [ ], /* of size n. Head pointers for bucket sort */ + Int Next [ ], /* of size n. Next pointers for bucket sort */ + Int Ci [ ], /* size nz */ + Int Cp [ ] /* size n+1 */ +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry aij ; + double cmax, value, rs, ctol, dvalue ; + Int k, p, row, col, do_values, do_sum, do_max, do_scale, nweak, weak, + p1, p2, dfound, unmatched, n2, oldrow, newrow, oldcol, newcol, pp ; +#ifdef COMPLEX + Int split = SPLIT (Az) ; +#endif +#ifndef NRECIPROCAL + Int do_recip = FALSE ; +#endif + +#ifndef NDEBUG + /* UMF_debug += 99 ; */ + DEBUGm3 (("\n ==================================UMF_2by2: tol %g\n", tol)) ; + ASSERT (AMD_valid (n, n, Ap, Ai)) ; + for (k = n1 ; k < n - nempty ; k++) + { + ASSERT (Cperm1 [k] == Rperm1 [k]) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* determine scaling options */ + /* ---------------------------------------------------------------------- */ + + /* use the values, but only if they are present */ + /* ignore the values if tol <= 0 */ + do_values = (tol > 0) && (Ax != (double *) NULL) ; + if (do_values && (Rs != (double *) NULL)) + { + do_sum = (scale == UMFPACK_SCALE_SUM) ; + do_max = (scale == UMFPACK_SCALE_MAX) ; + } + else + { + /* no scaling */ + do_sum = FALSE ; + do_max = FALSE ; + } + do_scale = do_max || do_sum ; + DEBUGm3 (("do_values "ID" do_sum "ID" do_max "ID" do_scale "ID"\n", + do_values, do_sum, do_max, do_scale)) ; + + /* ---------------------------------------------------------------------- */ + /* compute the row scaling, if requested */ + /* ---------------------------------------------------------------------- */ + + /* see also umf_kernel_init */ + + if (do_scale) + { +#ifndef NRECIPROCAL + double rsmin ; +#endif + for (row = 0 ; row < n ; row++) + { + Rs [row] = 0.0 ; + } + for (col = 0 ; col < n ; col++) + { + p2 = Ap [col+1] ; + for (p = Ap [col] ; p < p2 ; p++) + { + row = Ai [p] ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + rs = Rs [row] ; + if (!SCALAR_IS_NAN (rs)) + { + if (SCALAR_IS_NAN (value)) + { + /* if any entry in a row is NaN, then the scale factor + * for the row is NaN. It will be set to 1 later. */ + Rs [row] = value ; + } + else if (do_max) + { + Rs [row] = MAX (rs, value) ; + } + else + { + Rs [row] += value ; + } + } + } + } +#ifndef NRECIPROCAL + rsmin = Rs [0] ; + if (SCALAR_IS_ZERO (rsmin) || SCALAR_IS_NAN (rsmin)) + { + rsmin = 1.0 ; + } +#endif + for (row = 0 ; row < n ; row++) + { + /* do not scale an empty row, or a row with a NaN */ + rs = Rs [row] ; + if (SCALAR_IS_ZERO (rs) || SCALAR_IS_NAN (rs)) + { + Rs [row] = 1.0 ; + } +#ifndef NRECIPROCAL + rsmin = MIN (rsmin, Rs [row]) ; +#endif + } + +#ifndef NRECIPROCAL + /* multiply by the reciprocal if Rs is not too small */ + do_recip = (rsmin >= RECIPROCAL_TOLERANCE) ; + if (do_recip) + { + /* invert the scale factors */ + for (row = 0 ; row < n ; row++) + { + Rs [row] = 1.0 / Rs [row] ; + } + } +#endif + } + + /* ---------------------------------------------------------------------- */ + /* compute the max in each column and find diagonal */ + /* ---------------------------------------------------------------------- */ + + nweak = 0 ; + +#ifndef NDEBUG + for (k = 0 ; k < n ; k++) + { + ASSERT (Rperm1 [k] >= 0 && Rperm1 [k] < n) ; + ASSERT (InvRperm1 [Rperm1 [k]] == k) ; + } +#endif + + n2 = n - n1 - nempty ; + + /* use Ri to count the number of strong entries in each row */ + for (row = 0 ; row < n2 ; row++) + { + Ri [row] = 0 ; + } + + pp = 0 ; + ctol = 0 ; + dvalue = 1 ; + + /* construct C = pruned submatrix, strong values only, column form */ + + for (k = n1 ; k < n - nempty ; k++) + { + oldcol = Cperm1 [k] ; + newcol = k - n1 ; + Next [newcol] = EMPTY ; + DEBUGm1 (("Column "ID" newcol "ID" oldcol "ID"\n", k, newcol, oldcol)) ; + + Cp [newcol] = pp ; + + dfound = FALSE ; + p1 = Ap [oldcol] ; + p2 = Ap [oldcol+1] ; + if (do_values) + { + cmax = 0 ; + dvalue = 0 ; + + if (!do_scale) + { + /* no scaling */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + ASSERT (oldrow >= 0 && oldrow < n) ; + newrow = InvRperm1 [oldrow] - n1 ; + ASSERT (newrow >= -n1 && newrow < n2) ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + /* if either cmax or value is NaN, define cmax as NaN */ + if (!SCALAR_IS_NAN (cmax)) + { + if (SCALAR_IS_NAN (value)) + { + cmax = value ; + } + else + { + cmax = MAX (cmax, value) ; + } + } + if (oldrow == oldcol) + { + /* we found the diagonal entry in this column */ + dvalue = value ; + dfound = TRUE ; + ASSERT (newrow == newcol) ; + } + } + } +#ifndef NRECIPROCAL + else if (do_recip) + { + /* multiply by the reciprocal */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + ASSERT (oldrow >= 0 && oldrow < n) ; + newrow = InvRperm1 [oldrow] - n1 ; + ASSERT (newrow >= -n1 && newrow < n2) ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + value *= Rs [oldrow] ; + /* if either cmax or value is NaN, define cmax as NaN */ + if (!SCALAR_IS_NAN (cmax)) + { + if (SCALAR_IS_NAN (value)) + { + cmax = value ; + } + else + { + cmax = MAX (cmax, value) ; + } + } + if (oldrow == oldcol) + { + /* we found the diagonal entry in this column */ + dvalue = value ; + dfound = TRUE ; + ASSERT (newrow == newcol) ; + } + } + } +#endif + else + { + /* divide instead */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + ASSERT (oldrow >= 0 && oldrow < n) ; + newrow = InvRperm1 [oldrow] - n1 ; + ASSERT (newrow >= -n1 && newrow < n2) ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + value /= Rs [oldrow] ; + /* if either cmax or value is NaN, define cmax as NaN */ + if (!SCALAR_IS_NAN (cmax)) + { + if (SCALAR_IS_NAN (value)) + { + cmax = value ; + } + else + { + cmax = MAX (cmax, value) ; + } + } + if (oldrow == oldcol) + { + /* we found the diagonal entry in this column */ + dvalue = value ; + dfound = TRUE ; + ASSERT (newrow == newcol) ; + } + } + } + + ctol = tol * cmax ; + DEBUGm1 ((" cmax col "ID" %g ctol %g\n", oldcol, cmax, ctol)) ; + } + else + { + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + ASSERT (oldrow >= 0 && oldrow < n) ; + newrow = InvRperm1 [oldrow] - n1 ; + ASSERT (newrow >= -n1 && newrow < n2) ; + if (newrow < 0) continue ; + Ci [pp++] = newrow ; + if (oldrow == oldcol) + { + /* we found the diagonal entry in this column */ + ASSERT (newrow == newcol) ; + dfound = TRUE ; + } + /* count the entries in each column */ + Ri [newrow]++ ; + } + } + + /* ------------------------------------------------------------------ */ + /* flag the weak diagonals */ + /* ------------------------------------------------------------------ */ + + if (!dfound) + { + /* no diagonal entry present */ + weak = TRUE ; + } + else + { + /* diagonal entry is present, check its value */ + weak = (do_values) ? WEAK (dvalue, ctol) : FALSE ; + } + if (weak) + { + /* flag this column as weak */ + DEBUG0 (("Weak!\n")) ; + Next [newcol] = IS_WEAK ; + nweak++ ; + } + + /* ------------------------------------------------------------------ */ + /* count entries in each row that are not numerically weak */ + /* ------------------------------------------------------------------ */ + + if (do_values) + { + if (!do_scale) + { + /* no scaling */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + newrow = InvRperm1 [oldrow] - n1 ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + weak = WEAK (value, ctol) ; + if (!weak) + { + DEBUG0 ((" strong: row "ID": %g\n", oldrow, value)) ; + Ci [pp++] = newrow ; + Ri [newrow]++ ; + } + } + } +#ifndef NRECIPROCAL + else if (do_recip) + { + /* multiply by the reciprocal */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + newrow = InvRperm1 [oldrow] - n1 ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + value *= Rs [oldrow] ; + weak = WEAK (value, ctol) ; + if (!weak) + { + DEBUG0 ((" strong: row "ID": %g\n", oldrow, value)) ; + Ci [pp++] = newrow ; + Ri [newrow]++ ; + } + } + } +#endif + else + { + /* divide instead */ + for (p = p1 ; p < p2 ; p++) + { + oldrow = Ai [p] ; + newrow = InvRperm1 [oldrow] - n1 ; + if (newrow < 0) continue ; + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + value /= Rs [oldrow] ; + weak = WEAK (value, ctol) ; + if (!weak) + { + DEBUG0 ((" strong: row "ID": %g\n", oldrow, value)) ; + Ci [pp++] = newrow ; + Ri [newrow]++ ; + } + } + } + } + } + Cp [n2] = pp ; + ASSERT (AMD_valid (n2, n2, Cp, Ci)) ; + + if (nweak == 0) + { + /* nothing to do, quick return */ + DEBUGm2 (("\n =============================UMF_2by2: quick return\n")) ; + for (k = 0 ; k < n ; k++) + { + P [k] = k ; + } + *p_nweak = 0 ; + *p_unmatched = 0 ; + return ; + } + +#ifndef NDEBUG + for (k = 0 ; k < n2 ; k++) + { + P [k] = EMPTY ; + } + for (k = 0 ; k < n2 ; k++) + { + ASSERT (Degree [k] >= 0 && Degree [k] < n2) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* find the 2-by-2 permutation */ + /* ---------------------------------------------------------------------- */ + + /* The matrix S is now mapped to the index range 0 to n2-1. We have + * S = A (Rperm [n1 .. n-nempty-1], Cperm [n1 .. n-nempty-1]), and then + * C = pattern of strong entries in S. A weak diagonal k in S is marked + * with Next [k] = IS_WEAK. */ + + unmatched = two_by_two (n2, Cp, Ci, Degree, Next, Ri, P, Rp, Head) ; + + /* ---------------------------------------------------------------------- */ + + *p_nweak = nweak ; + *p_unmatched = unmatched ; + +#ifndef NDEBUG + DEBUGm4 (("UMF_2by2: weak "ID" unmatched "ID"\n", nweak, unmatched)) ; + for (row = 0 ; row < n ; row++) + { + DEBUGm2 (("P ["ID"] = "ID"\n", row, P [row])) ; + } + DEBUGm2 (("\n =============================UMF_2by2: done\n\n")) ; +#endif +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.h b/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_2by2.h @@ -0,0 +1,36 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_2by2 +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + double tol, + Int scale, + Int Cperm1 [ ], +#ifndef NDEBUG + Int Rperm1 [ ], +#endif + Int InvRperm [ ], + Int n1, + Int nempty, + Int Degree [ ], + Int P [ ], + Int *p_nweak, + Int *p_nmatched, + Int Ri [ ], + Int Rp [ ], + double Rs [ ], + Int Head [ ], + Int Next [ ], + Int Si [ ], + Int Sp [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.c b/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.c @@ -0,0 +1,704 @@ +/* ========================================================================== */ +/* === UMF_analyze ========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Symbolic LL' factorization of A'*A, to get upper bounds on the size of + L and U for LU = PAQ, and to determine the frontal matrices and + (supernodal) column elimination tree. No fill-reducing column pre-ordering + is used. + + Returns TRUE if successful, FALSE if out of memory. UMF_analyze can only + run out of memory if anzmax (which is Ap [n_row]) is too small. + + Uses workspace of size O(nonzeros in A). On input, the matrix A is + stored in row-form at the tail end of Ai. It is destroyed on output. + The rows of A must be sorted by increasing first column index. + The matrix is assumed to be valid. + + Empty rows and columns have already been removed. + +*/ + +#include "umf_internal.h" +#include "umf_apply_order.h" +#include "umf_fsize.h" + +/* ========================================================================== */ + +GLOBAL Int UMF_analyze +( + Int n_row, /* A is n_row-by-n_col */ + Int n_col, + Int Ai [ ], /* Ai [Ap [0]..Ap[n_row]-1]: column indices */ + /* destroyed on output. Note that this is NOT the */ + /* user's Ai that was passed to UMFPACK_*symbolic */ + /* size of Ai, Ap [n_row] = anzmax >= anz + n_col */ + /* Ap [0] must be => n_col. The space to the */ + /* front of Ai is used as workspace. */ + + Int Ap [ ], /* of size MAX (n_row, n_col) + 1 */ + /* Ap [0..n_row]: row pointers */ + /* Row i is in Ai [Ap [i] ... Ap [i+1]-1] */ + + /* rows must have smallest col index first, or be */ + /* in sorted form. Used as workspace of size n_col */ + /* and destroyed. */ + + /* Note that this is NOT the */ + /* user's Ap that was passed to UMFPACK_*symbolic */ + + Int Up [ ], /* workspace of size n_col, and output column perm. + * for column etree postorder. */ + + Int fixQ, + + /* temporary workspaces: */ + Int W [ ], /* W [0..n_col-1] */ + Int Link [ ], /* Link [0..n_col-1] */ + + /* output: information about each frontal matrix: */ + Int Front_ncols [ ], /* size n_col */ + Int Front_nrows [ ], /* of size n_col */ + Int Front_npivcol [ ], /* of size n_col */ + Int Front_parent [ ], /* of size n_col */ + Int *nfr_out, + + Int *p_ncompactions /* number of compactions in UMF_analyze */ +) +{ + /* ====================================================================== */ + /* ==== local variables ================================================= */ + /* ====================================================================== */ + + Int j, j3, col, k, row, parent, j2, pdest, p, p2, thickness, npivots, nfr, + i, *Winv, kk, npiv, jnext, krow, knext, pfirst, jlast, ncompactions, + *Front_stack, *Front_order, *Front_child, *Front_sibling, + Wflag, npivcol, fallrows, fallcols, fpiv, frows, fcols, *Front_size ; + + nfr = 0 ; + DEBUG0 (("UMF_analyze: anzmax "ID" anrow "ID" ancol "ID"\n", + Ap [n_row], n_row, n_col)) ; + + /* ====================================================================== */ + /* ==== initializations ================================================= */ + /* ====================================================================== */ + +#pragma ivdep + for (j = 0 ; j < n_col ; j++) + { + Link [j] = EMPTY ; + W [j] = EMPTY ; + Up [j] = EMPTY ; + + /* Frontal matrix data structure: */ + Front_npivcol [j] = 0 ; /* number of pivot columns */ + Front_nrows [j] = 0 ; /* number of rows, incl. pivot rows */ + Front_ncols [j] = 0 ; /* number of cols, incl. pivot cols */ + Front_parent [j] = EMPTY ; /* parent front */ + /* Note that only non-pivotal columns are stored in a front (a "row" */ + /* of U) during elimination. */ + } + + /* the rows must be sorted by increasing min col */ + krow = 0 ; + pfirst = Ap [0] ; + jlast = EMPTY ; + jnext = EMPTY ; + Wflag = 0 ; + + /* this test requires the size of Ai to be >= n_col + nz */ + ASSERT (pfirst >= n_col) ; /* Ai must be large enough */ + + /* pdest points to the first free space in Ai */ + pdest = 0 ; + ncompactions = 0 ; + + /* ====================================================================== */ + /* === compute symbolic LL' factorization (unsorted) ==================== */ + /* ====================================================================== */ + + for (j = 0 ; j < n_col ; j = jnext) + { + DEBUG1 (("\n\n============Front "ID" starting. nfr = "ID"\n", j, nfr)) ; + + /* ================================================================== */ + /* === garbage collection =========================================== */ + /* ================================================================== */ + + if (pdest + (n_col-j) > pfirst) + { + /* we might run out ... compact the rows of U */ + +#ifndef NDEBUG + DEBUG0 (("UMF_analyze COMPACTION, j="ID" pfirst="ID"\n", + j, pfirst)) ; + for (row = 0 ; row < j ; row++) + { + if (Up [row] != EMPTY) + { + /* this is a live row of U */ + DEBUG1 (("Live row: "ID" cols: ", row)) ; + p = Up [row] ; + ASSERT (Front_ncols [row] > Front_npivcol [row]) ; + p2 = p + (Front_ncols [row] - Front_npivcol [row]) ; + for ( ; p < p2 ; p++) + { + DEBUG1 ((ID, Ai [p])) ; + ASSERT (p < pfirst) ; + ASSERT (Ai [p] > row && Ai [p] < n_col) ; + } + DEBUG1 (("\n")) ; + } + } + DEBUG1 (("\nStarting to compact:\n")) ; +#endif + + pdest = 0 ; + ncompactions++ ; + for (row = 0 ; row < j ; row++) + { + if (Up [row] != EMPTY) + { + /* this is a live row of U */ + DEBUG1 (("Live row: "ID" cols: ", row)) ; + ASSERT (row < n_col) ; + p = Up [row] ; + ASSERT (Front_ncols [row] > Front_npivcol [row]) ; + p2 = p + (Front_ncols [row] - Front_npivcol [row]) ; + Up [row] = pdest ; + for ( ; p < p2 ; p++) + { + DEBUG1 ((ID, Ai [p])) ; + ASSERT (p < pfirst) ; + ASSERT (Ai [p] > row && Ai [p] < n_col) ; + Ai [pdest++] = Ai [p] ; + ASSERT (pdest <= pfirst) ; + } + DEBUG1 (("\n")) ; + } + } + +#ifndef NDEBUG + DEBUG1 (("\nAFTER COMPACTION, j="ID" pfirst="ID"\n", j, pfirst)) ; + for (row = 0 ; row < j ; row++) + { + if (Up [row] != EMPTY) + { + /* this is a live row of U */ + DEBUG1 (("Live row: "ID" cols: ", row)) ; + p = Up [row] ; + ASSERT (Front_ncols [row] > Front_npivcol [row]) ; + p2 = p + (Front_ncols [row] - Front_npivcol [row]) ; + for ( ; p < p2 ; p++) + { + DEBUG1 ((ID, Ai [p])) ; + ASSERT (p < pfirst) ; + ASSERT (Ai [p] > row && Ai [p] < n_col) ; + } + DEBUG1 (("\n")) ; + } + } +#endif + + } + + if (pdest + (n_col-j) > pfirst) + { + /* :: out of memory in umf_analyze :: */ + /* it can't happen, if pfirst >= n_col */ + return (FALSE) ; /* internal error! */ + } + + /* ------------------------------------------------------------------ */ + /* is the last front a child of this one? */ + /* ------------------------------------------------------------------ */ + + if (jlast != EMPTY && Link [j] == jlast) + { + /* yes - create row j by appending to jlast */ + DEBUG1 (("GOT:last front is child of this one: j "ID" jlast "ID"\n", + j, jlast)) ; + ASSERT (jlast >= 0 && jlast < j) ; + + Up [j] = Up [jlast] ; + Up [jlast] = EMPTY ; + + /* find the parent, delete column j, and update W */ + parent = n_col ; + for (p = Up [j] ; p < pdest ; ) + { + j3 = Ai [p] ; + DEBUG1 (("Initial row of U: col "ID" ", j3)) ; + ASSERT (j3 >= 0 && j3 < n_col) ; + DEBUG1 (("W: "ID" \n", W [j3])) ; + ASSERT (W [j3] == Wflag) ; + if (j == j3) + { + DEBUG1 (("Found column j at p = "ID"\n", p)) ; + Ai [p] = Ai [--pdest] ; + } + else + { + if (j3 < parent) + { + parent = j3 ; + } + p++ ; + } + } + + /* delete jlast from the link list of j */ + Link [j] = Link [jlast] ; + + ASSERT (Front_nrows [jlast] > Front_npivcol [jlast]) ; + thickness = (Front_nrows [jlast] - Front_npivcol [jlast]) ; + DEBUG1 (("initial thickness: "ID"\n", thickness)) ; + + } + else + { + Up [j] = pdest ; + parent = n_col ; + /* thickness: number of (nonpivotal) rows in frontal matrix j */ + thickness = 0 ; + Wflag = j ; + } + + /* ================================================================== */ + /* === compute row j of A*A' ======================================== */ + /* ================================================================== */ + + /* ------------------------------------------------------------------ */ + /* flag the diagonal entry in row U, but do not add to pattern */ + /* ------------------------------------------------------------------ */ + + ASSERT (pdest <= pfirst) ; + W [j] = Wflag ; + + DEBUG1 (("\nComputing row "ID" of A'*A\n", j)) ; + DEBUG2 ((" col: "ID" (diagonal)\n", j)) ; + + /* ------------------------------------------------------------------ */ + /* find the rows the contribute to this column j */ + /* ------------------------------------------------------------------ */ + + jnext = n_col ; + for (knext = krow ; knext < n_row ; knext++) + { + ASSERT (Ap [knext] < Ap [knext+1]) ; + ASSERT (Ap [knext] >= pfirst && Ap [knext] <= Ap [n_row]) ; + jnext = Ai [Ap [knext]] ; + ASSERT (jnext >= j) ; + if (jnext != j) + { + break ; + } + } + + /* rows krow ... knext-1 all have first column index of j */ + /* (or are empty) */ + + /* row knext has first column index of jnext */ + /* if knext = n_row, then jnext is n_col */ + if (knext == n_row) + { + jnext = n_col ; + } + + ASSERT (jnext > j) ; + ASSERT (jnext <= n_col) ; + + /* ------------------------------------------------------------------ */ + /* for each nonzero A (k,j) in column j of A do: */ + /* ------------------------------------------------------------------ */ + + for (k = krow ; k < knext ; k++) + { + p = Ap [k] ; + p2 = Ap [k+1] ; + ASSERT (p < p2) ; + + /* merge row k of A into W */ + DEBUG2 ((" ---- A row "ID" ", k)) ; + ASSERT (k >= 0 && k < n_row) ; + ASSERT (Ai [p] == j) ; + DEBUG2 ((" p "ID" p2 "ID"\n cols:", p, p2)) ; + ASSERT (p >= pfirst && p < Ap [n_row]) ; + ASSERT (p2 > pfirst && p2 <= Ap [n_row]) ; + for ( ; p < p2 ; p++) + { + /* add to pattern if seen for the first time */ + col = Ai [p] ; + ASSERT (col >= j && col < n_col) ; + DEBUG3 ((" "ID, col)) ; + if (W [col] != Wflag) + { + Ai [pdest++] = col ; + ASSERT (pdest <= pfirst) ; + /* flag this column has having been seen for row j */ + W [col] = Wflag ; + if (col < parent) + { + parent = col ; + } + } + } + DEBUG2 (("\n")) ; + thickness++ ; + } + +#ifndef NDEBUG + DEBUG3 (("\nRow "ID" of A'A:\n", j)) ; + for (p = Up [j] ; p < pdest ; p++) + { + DEBUG3 ((" "ID, Ai [p])) ; + } + DEBUG3 (("\n")) ; +#endif + + /* ------------------------------------------------------------------ */ + /* delete rows up to but not including knext */ + /* ------------------------------------------------------------------ */ + + krow = knext ; + pfirst = Ap [knext] ; + + /* we can now use Ai [0..pfirst-1] as workspace for rows of U */ + + /* ================================================================== */ + /* === compute jth row of U ========================================= */ + /* ================================================================== */ + + /* for each nonzero U (k,j) in column j of U (1:j-1,:) do */ + for (k = Link [j] ; k != EMPTY ; k = Link [k]) + { + /* merge row k of U into W */ + DEBUG2 ((" ---- U row "ID, k)) ; + ASSERT (k >= 0 && k < n_col) ; + ASSERT (Up [k] != EMPTY) ; + p = Up [k] ; + ASSERT (Front_ncols [k] > Front_npivcol [k]) ; + p2 = p + (Front_ncols [k] - Front_npivcol [k]) ; + DEBUG2 ((" p "ID" p2 "ID"\n cols:", p, p2)) ; + ASSERT (p <= pfirst) ; + ASSERT (p2 <= pfirst) ; + for ( ; p < p2 ; p++) + { + /* add to pattern if seen for the first time */ + col = Ai [p] ; + ASSERT (col >= j && col < n_col) ; + DEBUG3 ((" "ID, col)) ; + if (W [col] != Wflag) + { + Ai [pdest++] = col ; + ASSERT (pdest <= pfirst) ; + /* flag this col has having been seen for row j */ + W [col] = Wflag ; + if (col < parent) + { + parent = col ; + } + } + } + DEBUG2 (("\n")) ; + + /* mark the row k as deleted */ + Up [k] = EMPTY ; + + ASSERT (Front_nrows [k] > Front_npivcol [k]) ; + thickness += (Front_nrows [k] - Front_npivcol [k]) ; + ASSERT (Front_parent [k] == j) ; + } + +#ifndef NDEBUG + DEBUG3 (("\nRow "ID" of U prior to supercolumn detection:\n", j)); + for (p = Up [j] ; p < pdest ; p++) + { + DEBUG3 ((" "ID, Ai [p])) ; + } + DEBUG3 (("\n")) ; + DEBUG1 (("thickness, prior to supercol detect: "ID"\n", thickness)) ; +#endif + + /* ================================================================== */ + /* === quicky mass elimination ====================================== */ + /* ================================================================== */ + + /* this code detects some supernodes, but it might miss */ + /* some because the elimination tree (created on the fly) */ + /* is not yet post-ordered, and because the pattern of A'*A */ + /* is also computed on the fly. */ + + /* j2 is incremented because the pivot columns are not stored */ + + for (j2 = j+1 ; j2 < jnext ; j2++) + { + ASSERT (j2 >= 0 && j2 < n_col) ; + if (W [j2] != Wflag || Link [j2] != EMPTY) + { + break ; + } + } + + /* the loop above terminated with j2 at the first non-supernode */ + DEBUG1 (("jnext = "ID"\n", jnext)) ; + ASSERT (j2 <= jnext) ; + jnext = j2 ; + j2-- ; + DEBUG1 (("j2 = "ID"\n", j2)) ; + ASSERT (j2 < n_col) ; + + npivots = j2-j+1 ; + DEBUG1 (("Number of pivot columns: "ID"\n", npivots)) ; + + /* rows j:j2 have the same nonzero pattern, except for columns j:j2-1 */ + + if (j2 > j) + { + /* supernode detected, prune the pattern of new row j */ + ASSERT (parent == j+1) ; + ASSERT (j2 < n_col) ; + DEBUG1 (("Supernode detected, j "ID" to j2 "ID"\n", j, j2)) ; + + parent = n_col ; + p2 = pdest ; + pdest = Up [j] ; + for (p = Up [j] ; p < p2 ; p++) + { + col = Ai [p] ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (W [col] == Wflag) ; + if (col > j2) + { + /* keep this col in the pattern of the new row j */ + Ai [pdest++] = col ; + if (col < parent) + { + parent = col ; + } + } + } + } + + DEBUG1 (("Parent ["ID"] = "ID"\n", j, parent)) ; + ASSERT (parent > j2) ; + + if (parent == n_col) + { + /* this front has no parent - it is the root of a subtree */ + parent = EMPTY ; + } + +#ifndef NDEBUG + DEBUG3 (("\nFinal row "ID" of U after supercolumn detection:\n", j)) ; + for (p = Up [j] ; p < pdest ; p++) + { + ASSERT (Ai [p] >= 0 && Ai [p] < n_col) ; + DEBUG3 ((" "ID" ("ID")", Ai [p], W [Ai [p]])) ; + ASSERT (W [Ai [p]] == Wflag) ; + } + DEBUG3 (("\n")) ; +#endif + + /* ================================================================== */ + /* === frontal matrix =============================================== */ + /* ================================================================== */ + + /* front has Front_npivcol [j] pivot columns */ + /* entire front is Front_nrows [j] -by- Front_ncols [j] */ + /* j is first column in the front */ + + npivcol = npivots ; + fallrows = thickness ; + fallcols = npivots + pdest - Up [j] ; + + /* number of pivots in the front (rows and columns) */ + fpiv = MIN (npivcol, fallrows) ; + + /* size of contribution block */ + frows = fallrows - fpiv ; + fcols = fallcols - fpiv ; + + if (frows == 0 || fcols == 0) + { + /* front has no contribution block and thus needs no parent */ + DEBUG1 (("Frontal matrix evaporation\n")) ; + Up [j] = EMPTY ; + parent = EMPTY ; + } + + Front_npivcol [j] = npivots ; + Front_nrows [j] = fallrows ; + Front_ncols [j] = fallcols ; + Front_parent [j] = parent ; + ASSERT (npivots > 0) ; + + /* Front_parent [j] is the first column of the parent frontal matrix */ + + DEBUG1 (("\n\n==== Front "ID", nfr "ID" pivot columns "ID":"ID + " all front: "ID"-by-"ID" Parent: "ID"\n", j, nfr, j,j+npivots-1, + Front_nrows [j], Front_ncols [j], Front_parent [j])) ; + nfr++ ; + + /* ================================================================== */ + /* === prepare this row for its parent ============================== */ + /* ================================================================== */ + + if (parent != EMPTY) + { + Link [j] = Link [parent] ; + Link [parent] = j ; + } + + ASSERT (jnext > j) ; + + jlast = j ; + } + + /* ====================================================================== */ + /* === postorder the fronts ============================================= */ + /* ====================================================================== */ + + *nfr_out = nfr ; + + Front_order = W ; /* use W for Front_order [ */ + + if (fixQ) + { + /* do not postorder the fronts if Q is fixed */ + DEBUG1 (("\nNo postorder (Q is fixed)\n")) ; + k = 0 ; + /* Pragma added May 14, 2003. The Intel compiler icl 6.0 (an old + * version) incorrectly vectorizes this loop. */ +#pragma novector + for (j = 0 ; j < n_col ; j++) + { + if (Front_npivcol [j] > 0) + { + Front_order [j] = k++ ; + DEBUG1 (("Front order of j: "ID" is:"ID"\n", j, + Front_order [j])) ; + } + else + { + Front_order [j] = EMPTY ; + } + } + } + else + { + + /* use Ap for Front_child and use Link for Front_sibling [ */ + Front_child = Ap ; + Front_sibling = Link ; + + /* use Ai for Front_stack, size of Ai is >= 2*n_col */ + Front_stack = Ai ; + Front_size = Front_stack + n_col ; + + UMF_fsize (n_col, Front_size, Front_nrows, Front_ncols, + Front_parent, Front_npivcol) ; + + AMD_postorder (n_col, Front_parent, Front_npivcol, Front_size, + Front_order, Front_child, Front_sibling, Front_stack) ; + + /* done with Front_child, Front_sibling, Front_size, and Front_stack ]*/ + + /* ------------------------------------------------------------------ */ + /* construct the column permutation (return in Up) */ + /* ------------------------------------------------------------------ */ + + /* Front_order [i] = k means that front i is kth front in the new order. + * i is in the range 0 to n_col-1, and k is in the range 0 to nfr-1 */ + + /* Use Ai as workspace for Winv [ */ + Winv = Ai ; + for (k = 0 ; k < nfr ; k++) + { + Winv [k] = EMPTY ; + } + + /* compute the inverse of Front_order, so that Winv [k] = i */ + /* if Front_order [i] = k */ + + DEBUG1 (("\n\nComputing output column permutation:\n")) ; + for (i = 0 ; i < n_col ; i++) + { + k = Front_order [i] ; + if (k != EMPTY) + { + DEBUG1 (("Front "ID" new order: "ID"\n", i, k)) ; + ASSERT (k >= 0 && k < nfr) ; + ASSERT (Winv [k] == EMPTY) ; + Winv [k] = i ; + } + } + + /* Use Up as output permutation */ + kk = 0 ; + for (k = 0 ; k < nfr ; k++) + { + i = Winv [k] ; + DEBUG1 (("Old Front "ID" New Front "ID" npivots "ID" nrows "ID + " ncols "ID"\n", + i, k, Front_npivcol [i], Front_nrows [i], Front_ncols [i])) ; + ASSERT (i >= 0 && i < n_col) ; + ASSERT (Front_npivcol [i] > 0) ; + for (npiv = 0 ; npiv < Front_npivcol [i] ; npiv++) + { + Up [kk] = i + npiv ; + DEBUG1 ((" Cperm ["ID"] = "ID"\n", kk, Up [kk])) ; + kk++ ; + } + } + ASSERT (kk == n_col) ; + + /* Winv no longer needed ] */ + } + + /* ---------------------------------------------------------------------- */ + /* apply the postorder traversal to renumber the frontal matrices */ + /* (or pack them in same order, if fixQ) */ + /* ---------------------------------------------------------------------- */ + + /* use Ai as workspace */ + + UMF_apply_order (Front_npivcol, Front_order, Ai, n_col, nfr) ; + UMF_apply_order (Front_nrows, Front_order, Ai, n_col, nfr) ; + UMF_apply_order (Front_ncols, Front_order, Ai, n_col, nfr) ; + UMF_apply_order (Front_parent, Front_order, Ai, n_col, nfr) ; + + /* fix the parent to refer to the new numbering */ + for (i = 0 ; i < nfr ; i++) + { + parent = Front_parent [i] ; + if (parent != EMPTY) + { + ASSERT (parent >= 0 && parent < n_col) ; + ASSERT (Front_order [parent] >= 0 && Front_order [parent] < nfr) ; + Front_parent [i] = Front_order [parent] ; + } + } + + /* Front_order longer needed ] */ + +#ifndef NDEBUG + DEBUG1 (("\nFinal frontal matrices:\n")) ; + for (i = 0 ; i < nfr ; i++) + { + DEBUG1 (("Final front "ID": npiv "ID" nrows "ID" ncols "ID" parent " + ID"\n", i, Front_npivcol [i], Front_nrows [i], + Front_ncols [i], Front_parent [i])) ; + } +#endif + + *p_ncompactions = ncompactions ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.h b/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_analyze.h @@ -0,0 +1,23 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_analyze +( + Int n_row, + Int n_col, + Int Ai [ ], + Int Ap [ ], + Int Up [ ], + Int fixQ, + Int Front_ncols [ ], + Int W [ ], + Int Link [ ], + Int Front_nrows [ ], + Int Front_npivcol [ ], + Int Front_parent [ ], + Int *nfr_out, + Int *p_ncompactions +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.c b/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.c @@ -0,0 +1,43 @@ +/* ========================================================================== */ +/* === UMF_apply_order ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Apply post-ordering of supernodal elimination tree. +*/ + +#include "umf_internal.h" + +GLOBAL void UMF_apply_order +( + Int Front [ ], /* of size nn on input, size nfr on output */ + const Int Order [ ], /* Order [i] = k, i in the range 0..nn-1, + * and k in the range 0..nfr-1, means that node + * i is the kth node in the postordered tree. */ + Int Temp [ ], /* workspace of size nfr */ + Int nn, /* nodes are numbered in the range 0..nn-1 */ + Int nfr /* the number of nodes actually in use */ +) +{ + Int i, k ; + for (i = 0 ; i < nn ; i++) + { + k = Order [i] ; + ASSERT (k >= EMPTY && k < nfr) ; + if (k != EMPTY) + { + Temp [k] = Front [i] ; + } + } + + for (k = 0 ; k < nfr ; k++) + { + Front [k] = Temp [k] ; + } +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.h b/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_apply_order.h @@ -0,0 +1,14 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_apply_order +( + Int Front [ ], + const Int Order [ ], + Int Temp [ ], + Int n_col, + Int nfr +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.c b/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.c @@ -0,0 +1,1215 @@ +/* ========================================================================== */ +/* === UMF_assemble ========================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Degree update and numerical assembly. This is compiled twice (with and + * without FIXQ) for each real/complex int/long version, for a total of 8 + * versions.*/ + +#include "umf_internal.h" +#include "umf_mem_free_tail_block.h" + +/* ========================================================================== */ +/* === row_assemble ========================================================= */ +/* ========================================================================== */ + +PRIVATE void row_assemble +( + Int row, + NumericType *Numeric, + WorkType *Work +) +{ + + Entry *S, *Fcblock, *Frow ; + Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Row_tuples, *Row_tlen, rdeg0, + f, nrows, ncols, *Rows, *Cols, col, ncolsleft, j ; + Tuple *tp, *tp1, *tp2, *tpend ; + Unit *Memory, *p ; + Element *ep ; + +#ifndef FIXQ + Int *Col_degree ; + Col_degree = Numeric->Cperm ; +#endif + + Row_tuples = Numeric->Uip ; + tpi = Row_tuples [row] ; + if (!tpi) return ; + + Memory = Numeric->Memory ; + E = Work->E ; + Fcpos = Work->Fcpos ; + Frpos = Work->Frpos ; + Row_degree = Numeric->Rperm ; + Row_tlen = Numeric->Uilen ; + E = Work->E ; + Memory = Numeric->Memory ; + rdeg0 = Work->rdeg0 ; + Fcblock = Work->Fcblock ; + +#ifndef NDEBUG + DEBUG6 (("SCAN2-row: "ID"\n", row)) ; + UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ; +#endif + + ASSERT (NON_PIVOTAL_ROW (row)) ; + + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Row_tlen [row] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + Rows = Cols + ep->ncols ; + if (Rows [f] == EMPTY) continue ; /* row already assembled */ + ASSERT (row == Rows [f] && row >= 0 && row < Work->n_row) ; + + if (ep->rdeg == rdeg0) + { + /* ------------------------------------------------------ */ + /* this is an old Lson - assemble just one row */ + /* ------------------------------------------------------ */ + + /* flag the row as assembled from the Lson */ + Rows [f] = EMPTY ; + + nrows = ep->nrows ; + ncols = ep->ncols ; + + p += UNITS (Int, ncols + nrows) ; + S = ((Entry *) p) + f ; + + DEBUG6 (("Old LSON: "ID"\n", e)) ; +#ifndef NDEBUG + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + + ncolsleft = ep->ncolsleft ; + + Frow = Fcblock + Frpos [row] ; + DEBUG6 (("LSON found (in scan2-row): "ID"\n", e)) ; + + Row_degree [row] -= ncolsleft ; + + if (ncols == ncolsleft) + { + /* -------------------------------------------------- */ + /* no columns assembled out this Lson yet */ + /* -------------------------------------------------- */ + +#pragma ivdep + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + ASSERT (col >= 0 && col < Work->n_col) ; +#ifndef FIXQ + Col_degree [col] -- ; +#endif + /* Frow [Fcpos [col]] += *S ; */ + ASSEMBLE (Frow [Fcpos [col]], *S) ; + S += nrows ; + } + + } + else + { + /* -------------------------------------------------- */ + /* some columns have been assembled out of this Lson */ + /* -------------------------------------------------- */ + +#pragma ivdep + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + if (col >= 0) + { + ASSERT (col < Work->n_col) ; +#ifndef FIXQ + Col_degree [col] -- ; +#endif + /* Frow [Fcpos [col]] += *S ; */ + ASSEMBLE (Frow [Fcpos [col]], *S) ; + } + S += nrows ; + } + + } + ep->nrowsleft-- ; + ASSERT (ep->nrowsleft > 0) ; + } + else + { + *tp2++ = *tp ; /* leave the tuple in the list */ + } + } + Row_tlen [row] = tp2 - tp1 ; + +#ifndef NDEBUG + DEBUG7 (("row assembled in scan2-row: "ID"\n", row)) ; + UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ; + DEBUG7 (("Current frontal matrix: (scan 1b)\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif +} + +/* ========================================================================== */ +/* === col_assemble ========================================================= */ +/* ========================================================================== */ + +PRIVATE void col_assemble +( + Int col, + NumericType *Numeric, + WorkType *Work +) +{ + + Entry *S, *Fcblock, *Fcol ; + Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Col_tuples, *Col_tlen, cdeg0, + f, nrows, ncols, *Rows, *Cols, row, nrowsleft, i ; + Tuple *tp, *tp1, *tp2, *tpend ; + Unit *Memory, *p ; + Element *ep ; + +#if !defined (FIXQ) || !defined (NDEBUG) + Int *Col_degree ; + Col_degree = Numeric->Cperm ; +#endif + + Col_tuples = Numeric->Lip ; + tpi = Col_tuples [col] ; + if (!tpi) return ; + + Memory = Numeric->Memory ; + E = Work->E ; + Fcpos = Work->Fcpos ; + Frpos = Work->Frpos ; + Row_degree = Numeric->Rperm ; + Col_tlen = Numeric->Lilen ; + E = Work->E ; + Memory = Numeric->Memory ; + cdeg0 = Work->cdeg0 ; + Fcblock = Work->Fcblock ; + + DEBUG6 (("SCAN2-col: "ID"\n", col)) ; +#ifndef NDEBUG + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; +#endif + + ASSERT (NON_PIVOTAL_COL (col)) ; + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Col_tlen [col] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + + if (Cols [f] == EMPTY) continue ; /* col already assembled */ + ASSERT (col == Cols [f] && col >= 0 && col < Work->n_col) ; + + if (ep->cdeg == cdeg0) + { + /* ------------------------------------------------------ */ + /* this is an old Uson - assemble just one col */ + /* ------------------------------------------------------ */ + + /* flag the col as assembled from the Uson */ + Cols [f] = EMPTY ; + + nrows = ep->nrows ; + ncols = ep->ncols ; + Rows = Cols + ncols ; + p += UNITS (Int, ncols + nrows) ; + S = ((Entry *) p) + f * nrows ; + + DEBUG6 (("Old USON: "ID"\n", e)) ; +#ifndef NDEBUG + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + + nrowsleft = ep->nrowsleft ; + + Fcol = Fcblock + Fcpos [col] ; + DEBUG6 (("USON found (in scan2-col): "ID"\n", e)) ; +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + if (nrows == nrowsleft) + { + /* -------------------------------------------------- */ + /* no rows assembled out of this Uson yet */ + /* -------------------------------------------------- */ + +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + ASSERT (row >= 0 && row < Work->n_row) ; + Row_degree [row]-- ; + /* Fcol [Frpos [row]] += S [i] ; */ + ASSEMBLE (Fcol [Frpos [row]], S [i]) ; + } + } + else + { + /* -------------------------------------------------- */ + /* some rows have been assembled out of this Uson */ + /* -------------------------------------------------- */ + +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) + { + ASSERT (row < Work->n_row) ; + Row_degree [row]-- ; + /* Fcol [Frpos [row]] += S [i] ; */ + ASSEMBLE (Fcol [Frpos [row]], S [i]) ; + } + } + } + ep->ncolsleft-- ; + ASSERT (ep->ncolsleft > 0) ; + } + else + { + *tp2++ = *tp ; /* leave the tuple in the list */ + } + } + Col_tlen [col] = tp2 - tp1 ; + +#ifndef NDEBUG + DEBUG7 (("Column assembled in scan2-col: "ID"\n", col)) ; + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; + DEBUG7 (("Current frontal matrix: after scan2-col\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + +} + + +/* ========================================================================== */ +/* === UMF_assemble / UMF_assemble_fixq ===================================== */ +/* ========================================================================== */ + +#ifndef FIXQ +GLOBAL void UMF_assemble +#else +GLOBAL void UMF_assemble_fixq +#endif +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int e, i, row, col, i2, nrows, ncols, f, tpi, extcdeg, extrdeg, rdeg0, + cdeg0, son_list, next, nrows_to_assemble, + ncols_to_assemble, ngetrows, j, j2, + nrowsleft, /* number of rows remaining in S */ + ncolsleft, /* number of columns remaining in S */ + prior_Lson, prior_Uson, *E, *Cols, *Rows, *Wm, *Woo, + *Row_tuples, *Row_degree, *Row_tlen, + *Col_tuples, *Col_tlen ; + Unit *Memory, *p ; + Element *ep ; + Tuple *tp, *tp1, *tp2, *tpend ; + Entry + *S, /* a pointer into the contribution block of a son */ + *Fcblock, /* current contribution block */ + *Fcol ; /* a column of FC */ + Int *Frpos, + *Fcpos, + fnrows, /* number of rows in contribution block in F */ + fncols ; /* number of columns in contribution block in F */ + +#if !defined (FIXQ) || !defined (NDEBUG) + Int *Col_degree ; +#endif + +#ifndef NDEBUG + Int n_row, n_col ; + n_row = Work->n_row ; + n_col = Work->n_col ; + DEBUG3 (("::Assemble SCANS 1-4\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + +#if !defined (FIXQ) || !defined (NDEBUG) + Col_degree = Numeric->Cperm ; /* not updated if FIXQ is true */ +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + fncols = Work->fncols ; + fnrows = Work->fnrows ; + Fcpos = Work->Fcpos ; + Frpos = Work->Frpos ; + Row_degree = Numeric->Rperm ; + Row_tuples = Numeric->Uip ; + Row_tlen = Numeric->Uilen ; + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + E = Work->E ; + Memory = Numeric->Memory ; + Wm = Work->Wm ; + Woo = Work->Woo ; + rdeg0 = Work->rdeg0 ; + cdeg0 = Work->cdeg0 ; + +#ifndef NDEBUG + DEBUG6 (("============================================\n")) ; + DEBUG6 (("Degree update, assembly.\n")) ; + DEBUG6 (("pivot row pattern: fncols="ID"\n", fncols)) ; + for (j = 0 ; j < fncols ; j++) + { + col = Work->Fcols [j] ; + DEBUG6 ((ID" ", col)) ; + ASSERT (Fcpos [col] == j * Work->fnr_curr) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + } + ASSERT (Fcpos [Work->pivcol] >= 0) ; + DEBUG6 (("pivcol: "ID" pos "ID" fnr_curr "ID" fncols "ID"\n", + Work->pivcol, Fcpos [Work->pivcol], Work->fnr_curr, fncols)) ; + ASSERT (Fcpos [Work->pivcol] < fncols * Work->fnr_curr) ; + DEBUG6 (("\npivot col pattern: fnrows="ID"\n", fnrows)) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Work->Frows [i] ; + DEBUG6 ((ID" ", row)) ; + ASSERT (Frpos [row] == i) ; + ASSERT (NON_PIVOTAL_ROW (row)) ; + } + DEBUG6 (("\n")) ; + ASSERT (Frpos [Work->pivrow] >= 0) ; + ASSERT (Frpos [Work->pivrow] < fnrows) ; + ASSERT (Work->Flublock == (Entry *) (Numeric->Memory + E [0])) ; + ASSERT (Work->Fcblock == Work->Flublock + Work->nb * + (Work->nb + Work->fnr_curr + Work->fnc_curr)) ; +#endif + + Fcblock = Work->Fcblock ; + + /* ---------------------------------------------------------------------- */ + /* determine the largest actual frontal matrix size (for Info only) */ + /* ---------------------------------------------------------------------- */ + + ASSERT (fnrows == Work->fnrows_new + 1) ; + ASSERT (fncols == Work->fncols_new + 1) ; + + Numeric->maxnrows = MAX (Numeric->maxnrows, fnrows) ; + Numeric->maxncols = MAX (Numeric->maxncols, fncols) ; + + /* this is safe from integer overflow, since the current frontal matrix + * is already allocated. */ + Numeric->maxfrsize = MAX (Numeric->maxfrsize, fnrows * fncols) ; + + /* ---------------------------------------------------------------------- */ + /* assemble from prior elements into the current frontal matrix */ + /* ---------------------------------------------------------------------- */ + + DEBUG2 (("New assemble start [prior_element:"ID"\n", Work->prior_element)) ; + + /* Currently no rows or columns are marked. No elements are scanned, */ + /* that is, (ep->next == EMPTY) is true for all elements */ + + son_list = 0 ; /* start creating son_list [ */ + + /* ---------------------------------------------------------------------- */ + /* determine if most recent element is Lson or Uson of current front */ + /* ---------------------------------------------------------------------- */ + + if (!Work->do_extend) + { + prior_Uson = ( Work->pivcol_in_front && !Work->pivrow_in_front) ; + prior_Lson = (!Work->pivcol_in_front && Work->pivrow_in_front) ; + if (prior_Uson || prior_Lson) + { + e = Work->prior_element ; + if (e != EMPTY) + { + ASSERT (E [e]) ; + p = Memory + E [e] ; + ep = (Element *) p ; + ep->next = son_list ; + son_list = e ; +#ifndef NDEBUG + DEBUG2 (("e "ID" is Prior son "ID" "ID"\n", + e, prior_Uson, prior_Lson)) ; + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + ASSERT (E [e]) ; + } + } + } + Work->prior_element = EMPTY ; + + /* ---------------------------------------------------------------------- */ + /* SCAN1-row: scan the element lists of each new row in the pivot col */ + /* and compute the external column degree for each frontal */ + /* ---------------------------------------------------------------------- */ + + for (i2 = Work->fscan_row ; i2 < fnrows ; i2++) + { + /* Get a row */ + row = Work->NewRows [i2] ; + if (row < 0) row = FLIP (row) ; + ASSERT (row >= 0 && row < n_row) ; + + DEBUG6 (("SCAN1-row: "ID"\n", row)) ; +#ifndef NDEBUG + UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ; +#endif + + ASSERT (NON_PIVOTAL_ROW (row)) ; + tpi = Row_tuples [row] ; + if (!tpi) continue ; + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Row_tlen [row] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Rows = ((Int *) p) + ep->ncols ; + if (Rows [f] == EMPTY) continue ; /* row already assembled */ + ASSERT (row == Rows [f]) ; + + if (ep->cdeg < cdeg0) + { + /* first time seen in scan1-row */ + ep->cdeg = ep->nrowsleft + cdeg0 ; + DEBUG6 (("e "ID" First seen: cdeg: "ID" ", e, ep->cdeg-cdeg0)) ; + ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ; + } + + ep->cdeg-- ; /* decrement external column degree */ + DEBUG6 (("e "ID" New ext col deg: "ID"\n", e, ep->cdeg - cdeg0)) ; + + /* this element is not yet in the new son list */ + if (ep->cdeg == cdeg0 && ep->next == EMPTY) + { + /* A new LUson or Uson has been found */ + ep->next = son_list ; + son_list = e ; + } + + ASSERT (ep->cdeg >= cdeg0) ; + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Row_tlen [row] = tp2 - tp1 ; + } + + /* ---------------------------------------------------------------------- */ + /* SCAN1-col: scan the element lists of each new col in the pivot row */ + /* and compute the external row degree for each frontal */ + /* ---------------------------------------------------------------------- */ + + for (j2 = Work->fscan_col ; j2 < fncols ; j2++) + { + /* Get a column */ + col = Work->NewCols [j2] ; + if (col < 0) col = FLIP (col) ; + ASSERT (col >= 0 && col < n_col) ; + + DEBUG6 (("SCAN 1-col: "ID"\n", col)) ; +#ifndef NDEBUG + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; +#endif + + ASSERT (NON_PIVOTAL_COL (col)) ; + tpi = Col_tuples [col] ; + if (!tpi) continue ; + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Col_tlen [col] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + if (Cols [f] == EMPTY) continue ; /* column already assembled */ + ASSERT (col == Cols [f]) ; + + if (ep->rdeg < rdeg0) + { + /* first time seen in scan1-col */ + ep->rdeg = ep->ncolsleft + rdeg0 ; + DEBUG6 (("e "ID" First seen: rdeg: "ID" ", e, ep->rdeg-rdeg0)) ; + ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ; + } + + ep->rdeg-- ; /* decrement external row degree */ + DEBUG6 (("e "ID" New ext row degree: "ID"\n", e, ep->rdeg-rdeg0)) ; + + if (ep->rdeg == rdeg0 && ep->next == EMPTY) + { + /* A new LUson or Lson has been found */ + ep->next = son_list ; + son_list = e ; + } + + ASSERT (ep->rdeg >= rdeg0) ; + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Col_tlen [col] = tp2 - tp1 ; + } + + /* ---------------------------------------------------------------------- */ + /* assemble new sons via full scans */ + /* ---------------------------------------------------------------------- */ + + next = EMPTY ; + + for (e = son_list ; e > 0 ; e = next) + { + ASSERT (e > 0 && e <= Work->nel && E [e]) ; + p = Memory + E [e] ; + DEBUG2 (("New son: "ID"\n", e)) ; +#ifndef NDEBUG + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + GET_ELEMENT (ep, p, Cols, Rows, ncols, nrows, S) ; + nrowsleft = ep->nrowsleft ; + ncolsleft = ep->ncolsleft ; + next = ep->next ; + ep->next = EMPTY ; + + extrdeg = (ep->rdeg < rdeg0) ? ncolsleft : (ep->rdeg - rdeg0) ; + extcdeg = (ep->cdeg < cdeg0) ? nrowsleft : (ep->cdeg - cdeg0) ; + ncols_to_assemble = ncolsleft - extrdeg ; + nrows_to_assemble = nrowsleft - extcdeg ; + DEBUG2 (("extrdeg "ID" extcdeg "ID"\n", extrdeg, extcdeg)) ; + + if (extrdeg == 0 && extcdeg == 0) + { + + /* -------------------------------------------------------------- */ + /* this is an LUson - assemble an entire contribution block */ + /* -------------------------------------------------------------- */ + + DEBUG6 (("LUson found: "ID"\n", e)) ; + + if (nrows == nrowsleft) + { + /* ---------------------------------------------------------- */ + /* no rows assembled out of this LUson yet */ + /* ---------------------------------------------------------- */ + + /* compute the compressed column offset vector*/ + /* [ use Wm [0..nrows-1] for offsets */ +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + Row_degree [row] -= ncolsleft ; + Wm [i] = Frpos [row] ; + } + + if (ncols == ncolsleft) + { + /* ------------------------------------------------------ */ + /* no rows or cols assembled out of LUson yet */ + /* ------------------------------------------------------ */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + /* Fcol [Wm [i]] += S [i] ; */ + ASSEMBLE (Fcol [Wm [i]], S [i]) ; + } + S += nrows ; + } + + + } + else + { + /* ------------------------------------------------------ */ + /* only cols have been assembled out of LUson */ + /* ------------------------------------------------------ */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + if (col >= 0) + { +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + /* Fcol [Wm [i]] += S [i] ; */ + ASSEMBLE (Fcol [Wm [i]], S [i]) ; + } + } + S += nrows ; + } + + } + /* ] done using Wm [0..nrows-1] for offsets */ + } + else + { + /* ---------------------------------------------------------- */ + /* some rows have been assembled out of this LUson */ + /* ---------------------------------------------------------- */ + + /* compute the compressed column offset vector*/ + /* [ use Woo,Wm [0..nrowsleft-1] for offsets */ + ngetrows = 0 ; + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) + { + Row_degree [row] -= ncolsleft ; + Woo [ngetrows] = i ; + Wm [ngetrows++] = Frpos [row] ; + } + } + ASSERT (ngetrows == nrowsleft) ; + + if (ncols == ncolsleft) + { + /* ------------------------------------------------------ */ + /* only rows have been assembled out of this LUson */ + /* ------------------------------------------------------ */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrowsleft ; i++) + { + /* Fcol [Wm [i]] += S [Woo [i]] ; */ + ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ; + } + S += nrows ; + } + + } + else + { + /* ------------------------------------------------------ */ + /* both rows and columns have been assembled out of LUson */ + /* ------------------------------------------------------ */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + if (col >= 0) + { +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrowsleft ; i++) + { + /* Fcol [Wm [i]] += S [Woo [i]] ; */ + ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ; + } + } + S += nrows ; + } + + } + /* ] done using Woo,Wm [0..nrowsleft-1] */ + } + + /* deallocate the element: remove from ordered list */ + UMF_mem_free_tail_block (Numeric, E [e]) ; + E [e] = 0 ; + + } + else if (extcdeg == 0) + { + + /* -------------------------------------------------------------- */ + /* this is a Uson - assemble all possible columns */ + /* -------------------------------------------------------------- */ + + DEBUG6 (("New USON: "ID"\n", e)) ; + ASSERT (extrdeg > 0) ; + + DEBUG6 (("New uson "ID" cols to do "ID"\n", e, ncols_to_assemble)) ; + + if (ncols_to_assemble > 0) + { + + Int skip = FALSE ; + if (ncols_to_assemble * 16 < ncols && nrows == 1) + { + /* this is a tall and thin frontal matrix consisting of + * only one column (most likely an original column). Do + * not assemble it. It cannot be the pivot column, since + * the pivot column element would be an LU son, not an Lson, + * of the current frontal matrix. */ + ASSERT (nrowsleft == 1) ; + ASSERT (Rows [0] >= 0 && Rows [0] < Work->n_row) ; + skip = TRUE ; + Work->any_skip = TRUE ; + } + + if (!skip) + { + + if (nrows == nrowsleft) + { + /* -------------------------------------------------- */ + /* no rows have been assembled out of this Uson yet */ + /* -------------------------------------------------- */ + + /* compute the compressed column offset vector */ + /* [ use Wm [0..nrows-1] for offsets */ +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + ASSERT (row >= 0 && row < n_row) ; + Row_degree [row] -= ncols_to_assemble ; + Wm [i] = Frpos [row] ; + } + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + if ((col >= 0) && (Fcpos [col] >= 0)) + { +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrows ; i++) + { + /* Fcol [Wm [i]] += S [i] ; */ + ASSEMBLE (Fcol [Wm [i]], S [i]) ; + } + /* flag the column as assembled from Uson */ + Cols [j] = EMPTY ; + } + S += nrows ; + } + + + /* ] done using Wm [0..nrows-1] for offsets */ + } + else + { + /* -------------------------------------------------- */ + /* some rows have been assembled out of this Uson */ + /* -------------------------------------------------- */ + + /* compute the compressed column offset vector*/ + /* [ use Woo,Wm [0..nrows-1] for offsets */ + ngetrows = 0 ; + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) + { + Row_degree [row] -= ncols_to_assemble ; + ASSERT (row < n_row && Frpos [row] >= 0) ; + Woo [ngetrows] = i ; + Wm [ngetrows++] = Frpos [row] ; + } + } + ASSERT (ngetrows == nrowsleft) ; + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + if ((col >= 0) && (Fcpos [col] >= 0)) + { +#ifndef FIXQ + Col_degree [col] -= nrowsleft ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrowsleft ; i++) + { + /* Fcol [Wm [i]] += S [Woo [i]] ; */ + ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ; + } + /* flag the column as assembled from Uson */ + Cols [j] = EMPTY ; + } + S += nrows ; + } + + /* ] done using Woo,Wm */ + } + ep->ncolsleft = extrdeg ; + } + } + + } + else + { + + /* -------------------------------------------------------------- */ + /* this is an Lson - assemble all possible rows */ + /* -------------------------------------------------------------- */ + + DEBUG6 (("New LSON: "ID"\n", e)) ; + ASSERT (extrdeg == 0 && extcdeg > 0) ; + + DEBUG6 (("New lson "ID" rows to do "ID"\n", e, nrows_to_assemble)) ; + + if (nrows_to_assemble > 0) + { + + Int skip = FALSE ; + if (nrows_to_assemble * 16 < nrows && ncols == 1) + { + /* this is a tall and thin frontal matrix consisting of + * only one column (most likely an original column). Do + * not assemble it. It cannot be the pivot column, since + * the pivot column element would be an LU son, not an Lson, + * of the current frontal matrix. */ + ASSERT (ncolsleft == 1) ; + ASSERT (Cols [0] >= 0 && Cols [0] < Work->n_col) ; + Work->any_skip = TRUE ; + skip = TRUE ; + } + + if (!skip) + { + + /* compute the compressed column offset vector */ + /* [ use Woo,Wm [0..nrows-1] for offsets */ + ngetrows = 0 ; + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if ((row >= 0) && (Frpos [row] >= 0)) + { + ASSERT (row < n_row) ; + Row_degree [row] -= ncolsleft ; + Woo [ngetrows] = i ; + Wm [ngetrows++] = Frpos [row] ; + /* flag the row as assembled from the Lson */ + Rows [i] = EMPTY ; + } + } + ASSERT (nrowsleft - ngetrows == extcdeg) ; + ASSERT (ngetrows == nrows_to_assemble) ; + + if (ncols == ncolsleft) + { + /* -------------------------------------------------- */ + /* no columns assembled out this Lson yet */ + /* -------------------------------------------------- */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + ASSERT (col >= 0 && col < n_col) ; +#ifndef FIXQ + Col_degree [col] -= nrows_to_assemble ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrows_to_assemble ; i++) + { + /* Fcol [Wm [i]] += S [Woo [i]] ; */ + ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ; + } + S += nrows ; + } + + + } + else + { + /* -------------------------------------------------- */ + /* some columns have been assembled out of this Lson */ + /* -------------------------------------------------- */ + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + ASSERT (col < n_col) ; + if (col >= 0) + { +#ifndef FIXQ + Col_degree [col] -= nrows_to_assemble ; +#endif + Fcol = Fcblock + Fcpos [col] ; +#pragma ivdep + for (i = 0 ; i < nrows_to_assemble ; i++) + { + /* Fcol [Wm [i]] += S [Woo [i]] ; */ + ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ; + } + } + S += nrows ; + } + + } + + /* ] done using Woo,Wm */ + + ep->nrowsleft = extcdeg ; + } + } + } + } + + /* Note that garbage collection, and build tuples */ + /* both destroy the son list. */ + + /* ] son_list now empty */ + + /* ---------------------------------------------------------------------- */ + /* If frontal matrix extended, assemble old L/Usons from new rows/cols */ + /* ---------------------------------------------------------------------- */ + + /* ---------------------------------------------------------------------- */ + /* SCAN2-row: assemble rows of old Lsons from the new rows */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG7 (("Current frontal matrix: (prior to scan2-row)\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + + /* rescan the pivot row */ + if (Work->any_skip) + { + row_assemble (Work->pivrow, Numeric, Work) ; + } + + if (Work->do_scan2row) + { + for (i2 = Work->fscan_row ; i2 < fnrows ; i2++) + { + /* Get a row */ + row = Work->NewRows [i2] ; + if (row < 0) row = FLIP (row) ; + ASSERT (row >= 0 && row < n_row) ; + if (!(row == Work->pivrow && Work->any_skip)) + { + /* assemble it */ + row_assemble (row, Numeric, Work) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* SCAN2-col: assemble columns of old Usons from the new columns */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG7 (("Current frontal matrix: (prior to scan2-col)\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + + /* rescan the pivot col */ + if (Work->any_skip) + { + col_assemble (Work->pivcol, Numeric, Work) ; + } + + if (Work->do_scan2col) + { + + for (j2 = Work->fscan_col ; j2 < fncols ; j2++) + { + /* Get a column */ + col = Work->NewCols [j2] ; + if (col < 0) col = FLIP (col) ; + ASSERT (col >= 0 && col < n_col) ; + if (!(col == Work->pivcol && Work->any_skip)) + { + /* assemble it */ + col_assemble (col, Numeric, Work) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* done. the remainder of this routine is used only when in debug mode */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + + /* ---------------------------------------------------------------------- */ + /* when debugging: make sure the assembly did everything that it could */ + /* ---------------------------------------------------------------------- */ + + DEBUG3 (("::Assemble done\n")) ; + + for (i2 = 0 ; i2 < fnrows ; i2++) + { + /* Get a row */ + row = Work->Frows [i2] ; + ASSERT (row >= 0 && row < n_row) ; + + DEBUG6 (("DEBUG SCAN 1: "ID"\n", row)) ; + UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ; + + ASSERT (NON_PIVOTAL_ROW (row)) ; + tpi = Row_tuples [row] ; + if (!tpi) continue ; + tp = (Tuple *) (Memory + tpi) ; + tpend = tp + Row_tlen [row] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + Rows = ((Int *) p) + ep->ncols ; + if (Rows [f] == EMPTY) continue ; /* row already assembled */ + ASSERT (row == Rows [f]) ; + extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ; + extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ; + DEBUG6 (( + "e "ID" After assembly ext row deg: "ID" ext col degree "ID"\n", + e, extrdeg, extcdeg)) ; + + if (Work->any_skip) + { + /* no Lsons in any row, except for very tall and thin ones */ + ASSERT (extrdeg >= 0) ; + if (extrdeg == 0) + { + /* this is an unassemble Lson */ + ASSERT (ep->ncols == 1) ; + ASSERT (ep->ncolsleft == 1) ; + col = Cols [0] ; + ASSERT (col != Work->pivcol) ; + } + } + else + { + /* no Lsons in any row */ + ASSERT (extrdeg > 0) ; + /* Uson external row degree is = number of cols left */ + ASSERT (IMPLIES (extcdeg == 0, extrdeg == ep->ncolsleft)) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + + for (j2 = 0 ; j2 < fncols ; j2++) + { + /* Get a column */ + col = Work->Fcols [j2] ; + ASSERT (col >= 0 && col < n_col) ; + + DEBUG6 (("DEBUG SCAN 2: "ID"\n", col)) ; +#ifndef FIXQ + UMF_dump_rowcol (1, Numeric, Work, col, TRUE) ; +#else + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; +#endif + + ASSERT (NON_PIVOTAL_COL (col)) ; + tpi = Col_tuples [col] ; + if (!tpi) continue ; + tp = (Tuple *) (Memory + tpi) ; + tpend = tp + Col_tlen [col] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + Rows = ((Int *) p) + ep->ncols ; + if (Cols [f] == EMPTY) continue ; /* column already assembled */ + ASSERT (col == Cols [f]) ; + extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ; + extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ; + DEBUG6 (("e "ID" After assembly ext col deg: "ID"\n", e, extcdeg)) ; + + if (Work->any_skip) + { + /* no Usons in any column, except for very tall and thin ones */ + ASSERT (extcdeg >= 0) ; + if (extcdeg == 0) + { + /* this is an unassemble Uson */ + ASSERT (ep->nrows == 1) ; + ASSERT (ep->nrowsleft == 1) ; + row = Rows [0] ; + ASSERT (row != Work->pivrow) ; + } + } + else + { + /* no Usons in any column */ + ASSERT (extcdeg > 0) ; + /* Lson external column degree is = number of rows left */ + ASSERT (IMPLIES (extrdeg == 0, extcdeg == ep->nrowsleft)) ; + } + } + } +#endif /* NDEBUG */ +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.h b/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_assemble.h @@ -0,0 +1,17 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_assemble +( + NumericType *Numeric, + WorkType *Work +) ; + +GLOBAL void UMF_assemble_fixq +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.c b/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.c @@ -0,0 +1,164 @@ +/* ========================================================================== */ +/* === UMF_blas3_update ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include "umf_internal.h" + +GLOBAL void UMF_blas3_update +( + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry *L, *U, *C, *LU ; + Int k, m, n, d, nb, dc ; + + DEBUG5 (("In UMF_blas3_update "ID" "ID" "ID"\n", + Work->fnpiv, Work->fnrows, Work->fncols)) ; + + k = Work->fnpiv ; + if (k == 0) + { + /* no work to do */ + return ; + } + + m = Work->fnrows ; + n = Work->fncols ; + + d = Work->fnr_curr ; + dc = Work->fnc_curr ; + nb = Work->nb ; + ASSERT (d >= 0 && (d % 2) == 1) ; + C = Work->Fcblock ; /* ldc is fnr_curr */ + L = Work->Flblock ; /* ldl is fnr_curr */ + U = Work->Fublock ; /* ldu is fnc_curr, stored by rows */ + LU = Work->Flublock ; /* nb-by-nb */ + +#ifndef NDEBUG + DEBUG5 (("DO RANK-NB UPDATE of frontal:\n")) ; + DEBUG5 (("DGEMM : "ID" "ID" "ID"\n", k, m, n)) ; + DEBUG7 (("C block: ")) ; UMF_dump_dense (C, d, m, n) ; + DEBUG7 (("A block: ")) ; UMF_dump_dense (L, d, m, k) ; + DEBUG7 (("B' block: ")) ; UMF_dump_dense (U, dc, n, k) ; + DEBUG7 (("LU block: ")) ; UMF_dump_dense (LU, nb, k, k) ; +#endif + + if (k == 1) + { + +#ifdef USE_NO_BLAS + + /* no BLAS available - use plain C code instead */ + Int i, j ; + + /* rank-1 outer product to update the C block */ + for (j = 0 ; j < n ; j++) + { + Entry u_j = U [j] ; + if (IS_NONZERO (u_j)) + { + Entry *c_ij, *l_is ; + c_ij = & C [j*d] ; + l_is = & L [0] ; +#pragma ivdep + for (i = 0 ; i < m ; i++) + { + /* C [i+j*d]-= L [i] * U [j] */ + MULT_SUB (*c_ij, *l_is, u_j) ; + c_ij++ ; + l_is++ ; + } + } + } + +#else + BLAS_GER (m, n, L, U, C, d) ; + +#endif /* USE_NO_BLAS */ + + } + else + { + +#ifdef USE_NO_BLAS + + /* no BLAS available - use plain C code instead */ + Int i, j, s ; + + /* triangular solve to update the U block */ + for (s = 0 ; s < k ; s++) + { + for (i = s+1 ; i < k ; i++) + { + Entry l_is = LU [i+s*nb] ; + if (IS_NONZERO (l_is)) + { + Entry *u_ij, *u_sj ; + u_ij = & U [i*dc] ; + u_sj = & U [s*dc] ; +#pragma ivdep + for (j = 0 ; j < n ; j++) + { + /* U [i*dc+j] -= LU [i+s*nb] * U [s*dc+j] ; */ + MULT_SUB (*u_ij, l_is, *u_sj) ; + u_ij++ ; + u_sj++ ; + } + } + } + } + + /* rank-k outer product to update the C block */ + /* C = C - L*U' (U is stored by rows, not columns) */ + for (s = 0 ; s < k ; s++) + { + for (j = 0 ; j < n ; j++) + { + Entry u_sj = U [j+s*dc] ; + if (IS_NONZERO (u_sj)) + { + Entry *c_ij, *l_is ; + c_ij = & C [j*d] ; + l_is = & L [s*d] ; +#pragma ivdep + for (i = 0 ; i < m ; i++) + { + /* C [i+j*d]-= L [i+s*d] * U [s*dc+j] */ + MULT_SUB (*c_ij, *l_is, u_sj) ; + c_ij++ ; + l_is++ ; + } + } + } + } + +#else + + BLAS_TRSM_RIGHT (n, k, LU, nb, U, dc) ; + BLAS_GEMM (m, n, k, L, U, dc, C, d) ; + +#endif /* USE_NO_BLAS */ + + } + +#ifndef NDEBUG + DEBUG5 (("RANK-NB UPDATE of frontal done:\n")) ; + DEBUG5 (("DGEMM : "ID" "ID" "ID"\n", k, m, n)) ; + DEBUG7 (("C block: ")) ; UMF_dump_dense (C, d, m, n) ; + DEBUG7 (("A block: ")) ; UMF_dump_dense (L, d, m, k) ; + DEBUG7 (("B' block: ")) ; UMF_dump_dense (U, dc, n, k) ; + DEBUG7 (("LU block: ")) ; UMF_dump_dense (LU, nb, k, k) ; +#endif + + DEBUG2 (("blas3 "ID" "ID" "ID"\n", k, Work->fnrows, Work->fncols)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.h b/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_blas3_update.h @@ -0,0 +1,10 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_blas3_update +( + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.c b/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.c @@ -0,0 +1,159 @@ +/* ========================================================================== */ +/* === UMF_build_tuples ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Construct the tuple lists from a set of packed elements (no holes in + elements, no internal or external fragmentation, and a packed (0..Work->nel) + element name space). Assume no tuple lists are currently allocated, but + that the tuple lengths have been initialized by UMF_tuple_lengths. + + Returns TRUE if successful, FALSE if not enough memory. +*/ + +#include "umf_internal.h" +#include "umf_mem_alloc_tail_block.h" + +GLOBAL Int UMF_build_tuples +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int e, nrows, ncols, nel, *Rows, *Cols, row, col, n_row, n_col, *E, + *Row_tuples, *Row_degree, *Row_tlen, + *Col_tuples, *Col_degree, *Col_tlen, n1 ; + Element *ep ; + Unit *p ; + Tuple tuple, *tp ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + E = Work->E ; + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ + Row_tuples = Numeric->Uip ; + Row_tlen = Numeric->Uilen ; + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + n_row = Work->n_row ; + n_col = Work->n_col ; + nel = Work->nel ; + n1 = Work->n1 ; + + DEBUG3 (("BUILD_TUPLES: n_row "ID" n_col "ID" nel "ID"\n", + n_row, n_col, nel)) ; + + /* ---------------------------------------------------------------------- */ + /* allocate space for the tuple lists */ + /* ---------------------------------------------------------------------- */ + + /* Garbage collection and memory reallocation have already attempted to */ + /* ensure that there is enough memory for all the tuple lists. If */ + /* memory allocation fails here, then there is nothing more to be done. */ + + for (row = n1 ; row < n_row ; row++) + { + if (NON_PIVOTAL_ROW (row)) + { + Row_tuples [row] = UMF_mem_alloc_tail_block (Numeric, + UNITS (Tuple, TUPLES (Row_tlen [row]))) ; + if (!Row_tuples [row]) + { + /* :: out of memory for row tuples :: */ + DEBUGm4 (("out of memory: build row tuples\n")) ; + return (FALSE) ; /* out of memory for row tuples */ + } + Row_tlen [row] = 0 ; + } + } + + /* push on stack in reverse order, so column tuples are in the order */ + /* that they will be deleted. */ + for (col = n_col-1 ; col >= n1 ; col--) + { + if (NON_PIVOTAL_COL (col)) + { + Col_tuples [col] = UMF_mem_alloc_tail_block (Numeric, + UNITS (Tuple, TUPLES (Col_tlen [col]))) ; + if (!Col_tuples [col]) + { + /* :: out of memory for col tuples :: */ + DEBUGm4 (("out of memory: build col tuples\n")) ; + return (FALSE) ; /* out of memory for col tuples */ + } + Col_tlen [col] = 0 ; + } + } + +#ifndef NDEBUG + UMF_dump_memory (Numeric) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* create the tuple lists (exclude element 0) */ + /* ---------------------------------------------------------------------- */ + + /* for all elements, in order of creation */ + for (e = 1 ; e <= nel ; e++) + { + DEBUG9 (("Adding tuples for element: "ID" at "ID"\n", e, E [e])) ; + ASSERT (E [e]) ; /* no external fragmentation */ + p = Numeric->Memory + E [e] ; + GET_ELEMENT_PATTERN (ep, p, Cols, Rows, ncols) ; + nrows = ep->nrows ; + ASSERT (e != 0) ; + ASSERT (e == 0 || nrows == ep->nrowsleft) ; + ASSERT (e == 0 || ncols == ep->ncolsleft) ; + tuple.e = e ; + for (tuple.f = 0 ; tuple.f < ncols ; tuple.f++) + { + col = Cols [tuple.f] ; + ASSERT (col >= n1 && col < n_col) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + ASSERT (Col_tuples [col]) ; + tp = ((Tuple *) (Numeric->Memory + Col_tuples [col])) + + Col_tlen [col]++ ; + *tp = tuple ; +#ifndef NDEBUG + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; +#endif + } + for (tuple.f = 0 ; tuple.f < nrows ; tuple.f++) + { + row = Rows [tuple.f] ; + ASSERT (row >= n1 && row < n_row) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + ASSERT (Row_tuples [row]) ; + tp = ((Tuple *) (Numeric->Memory + Row_tuples [row])) + + Row_tlen [row]++ ; + *tp = tuple ; +#ifndef NDEBUG + UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ; +#endif + } + } + + /* ---------------------------------------------------------------------- */ + /* the tuple lists are now valid, and can be scanned */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_dump_memory (Numeric) ; + UMF_dump_matrix (Numeric, Work, FALSE) ; +#endif + DEBUG3 (("BUILD_TUPLES: done\n")) ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.h b/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_build_tuples.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_build_tuples +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.c b/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.c @@ -0,0 +1,3139 @@ +/* ========================================================================== */ +/* === UMF_colamd =========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* +UMF_colamd: an approximate minimum degree column ordering algorithm, + used as a preordering for UMFPACK. + +NOTE: if this routine is used outside of UMFPACK, for a sparse Cholesky +factorization of (AQ)'*(AQ) or a QR factorization of A, then one line should +be removed (the "&& pivot_row_thickness > 0" expression). See the comment +regarding the Cholesky factorization, below. + +Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization of + (AQ)'(AQ) has less fill-in and requires fewer floating point operations + than A'A. This also provides a good ordering for sparse partial + pivoting methods, P(AQ) = LU, where Q is computed prior to numerical + factorization, and P is computed during numerical factorization via + conventional partial pivoting with row interchanges. Colamd is the + column ordering method used in SuperLU, part of the ScaLAPACK library. + It is also available as built-in function in MATLAB Version 6, + available from MathWorks, Inc. (http://www.mathworks.com). This + routine can be used in place of colmmd in MATLAB. By default, the \ + and / operators in MATLAB perform a column ordering (using colmmd + or colamd) prior to LU factorization using sparse partial pivoting, + in the built-in MATLAB lu(A) routine. + + This code is derived from Colamd Version 2.0. + +Authors: + + The authors of the COLAMD code itself are Stefan I. Larimore and Timothy A. + Davis, University of Florida. The algorithm was developed in collaboration + with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. + The AMD metric on which this is based is by Patrick Amestoy, T. Davis, + and Iain Duff. + +Date: + + UMFPACK Version: see above. + COLAMD Version 2.0 was released on January 31, 2000. + +Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974, DMS-9803599, and CCR-0203270. + +UMFPACK: Copyright (c) 2003 by Timothy A. Davis. All Rights Reserved. + +See the UMFPACK README file for the License for your use of this code. + +Availability: + + Both UMFPACK and the original unmodified colamd/symamd library are + available at http://www.cise.ufl.edu/research/sparse. + +Changes for inclusion in UMFPACK: + + * symamd, symamd_report, and colamd_report removed + + * additional terms added to RowInfo, ColInfo, and stats + + * Frontal matrix information computed for UMFPACK + + * routines renamed + + * column elimination tree post-ordering incorporated. In the original + version 2.0, this was performed in colamd.m. + +For more information, see: + + Amestoy, P. R. and Davis, T. A. and Duff, I. S., + An approximate minimum degree ordering algorithm, + SIAM J. Matrix Analysis and Applic, vol 17, no 4., pp 886-905, 1996. + + Davis, T. A. and Gilbert, J. R. and Larimore, S. I. and Ng, E. G., + A column approximate minimum degree ordering algorithm, + Univ. of Florida, CISE Dept., TR-00-005, Gainesville, FL + Oct. 2000. Submitted to ACM Trans. Math. Softw. + +*/ + +/* ========================================================================== */ +/* === Description of user-callable routines ================================ */ +/* ========================================================================== */ + +/* + ---------------------------------------------------------------------------- + colamd_recommended: removed for UMFPACK + ---------------------------------------------------------------------------- + + ---------------------------------------------------------------------------- + colamd_set_defaults: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; + + Purpose: + + Sets the default parameters. The use of this routine is optional. + + Arguments: + + double knobs [COLAMD_KNOBS] ; Output only. + + Let c = knobs [COLAMD_DENSE_COL], r = knobs [COLAMD_DENSE_ROW]. + Colamd: rows with more than max (16, r*16*sqrt(n_col)) + entries are removed prior to ordering. Columns with more than + max (16, c*16*sqrt(n_row)) entries are removed prior to + ordering, and placed last in the output column ordering. + + Symamd: removed for UMFPACK. + + COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, + respectively, in colamd.h. Default values of these two knobs + are both 0.5. Currently, only knobs [0] and knobs [1] are + used, but future versions may use more knobs. If so, they will + be properly set to their defaults by the future version of + colamd_set_defaults, so that the code that calls colamd will + not need to change, assuming that you either use + colamd_set_defaults, or pass a (double *) NULL pointer as the + knobs array to colamd or symamd. + + knobs [COLAMD_AGGRESSIVE]: if nonzero, then perform aggressive + absorption. Otherwise, do not. This version does aggressive + absorption by default. COLAMD v2.1 (in MATLAB) always + does aggressive absorption (it doesn't have an option to turn + it off). + + ---------------------------------------------------------------------------- + colamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + Int UMF_colamd (Int n_row, Int n_col, Int Alen, Int *A, Int *p, + double knobs [COLAMD_KNOBS], Int stats [COLAMD_STATS]) ; + + Purpose: + + Computes a column ordering (Q) of A such that P(AQ)=LU or + (AQ)'AQ=LL' have less fill-in and require fewer floating point + operations than factorizing the unpermuted matrix A or A'A, + respectively. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + Int n_row ; Input argument. + + Number of rows in the matrix A. + Restriction: n_row >= 0. + Colamd returns FALSE if n_row is negative. + + Int n_col ; Input argument. + + Number of columns in the matrix A. + Restriction: n_col >= 0. + Colamd returns FALSE if n_col is negative. + + Int Alen ; Input argument. + + Restriction (see note): + Alen >= 2*nnz + 8*(n_col+1) + 6*(n_row+1) + n_col + Colamd returns FALSE if these conditions are not met. + + Note: this restriction makes an modest assumption regarding + the size of the two typedef's structures in colamd.h. + We do, however, guarantee that + + Alen >= UMF_COLAMD_RECOMMENDED (nnz, n_row, n_col) + + will be sufficient. + + Int A [Alen] ; Input and output argument. + + A is an integer array of size Alen. Alen must be at least as + large as the bare minimum value given above, but this is very + low, and can result in excessive run time. For best + performance, we recommend that Alen be greater than or equal to + UMF_COLAMD_RECOMMENDED (nnz, n_row, n_col), which adds + nnz/5 to the bare minimum value given above. + + On input, the row indices of the entries in column c of the + matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices + in a given column c need not be in ascending order, and + duplicate row indices may be be present. However, colamd will + work a little faster if both of these conditions are met + (Colamd puts the matrix into this format, if it finds that the + the conditions are not met). + + The matrix is 0-based. That is, rows are in the range 0 to + n_row-1, and columns are in the range 0 to n_col-1. Colamd + returns FALSE if any row index is out of range. + + A holds the inverse permutation on output. + + Int p [n_col+1] ; Both input and output argument. + + p is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n_col-1. The value p [n_col] is + thus the total number of entries in the pattern of the matrix A. + Colamd returns FALSE if these conditions are not met. + + On output, if colamd returns TRUE, the array p holds the column + permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is + the first column index in the new ordering, and p [n_col-1] is + the last. That is, p [k] = j means that column j of A is the + kth pivot column, in AQ, where k is in the range 0 to n_col-1 + (p [0] = j means that column j of A is the first column in AQ). + + If colamd returns FALSE, then no permutation is returned, and + p is undefined on output. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + The behavior is undefined if knobs contains NaN's. + (UMFPACK does not call umf_colamd with NaN-valued knobs). + + Int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Colamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty rows ignored. + + stats [1]: number of dense or empty columns ignored (and + ordered last in the output permutation p) + Note that a row can become "empty" if it + contains only "dense" and/or "empty" columns, + and similarly a column can become "empty" if it + only contains "dense" and/or "empty" rows. + + stats [2]: number of garbage collections performed. + This can be excessively high if Alen is close + to the minimum required value. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + -11 Columns of input matrix jumbled + (unsorted columns or duplicate entries). + + stats [4]: the bad column index + stats [5]: the bad row index + + -1 A is a null pointer + + -2 p is a null pointer + + -3 n_row is negative + + stats [4]: n_row + + -4 n_col is negative + + stats [4]: n_col + + -5 number of nonzeros in matrix is negative + + stats [4]: number of nonzeros, p [n_col] + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 A is too small + + stats [4]: required size + stats [5]: actual size (Alen) + + -8 a column has a zero or negative number of + entries (changed for UMFPACK) + + stats [4]: column with <= 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 unused + + -999 (unused; see symamd.c) + + Future versions may return more statistics in the stats array. + + Example: + + See http://www.cise.ufl.edu/~davis/colamd/example.c + for a complete example. + + To order the columns of a 5-by-4 matrix with 11 nonzero entries in + the following nonzero pattern + + x 0 x 0 + x 0 x x + 0 x x 0 + 0 0 x x + x x 0 0 + + with default knobs and no output statistics, do the following: + + #include "colamd.h" + #define ALEN UMF_COLAMD_RECOMMENDED (11, 5, 4) + Int A [ALEN] = {1, 2, 5, 3, 5, 1, 2, 3, 4, 2, 4} ; + Int p [ ] = {0, 3, 5, 9, 11} ; + Int stats [COLAMD_STATS] ; + UMF_colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; + + The permutation is returned in the array p, and A is destroyed. + + + ---------------------------------------------------------------------------- + symamd: does not appear in this version for UMFPACK + ---------------------------------------------------------------------------- + + ---------------------------------------------------------------------------- + colamd_report: does not appear in this version for UMFPACK + ---------------------------------------------------------------------------- + + ---------------------------------------------------------------------------- + symamd_report: does not appear in this version for UMFPACK + ---------------------------------------------------------------------------- + +*/ + +/* ========================================================================== */ +/* === Scaffolding code definitions ======================================== */ +/* ========================================================================== */ + +/* UMFPACK debugging control moved to amd_internal.h */ + +/* + Our "scaffolding code" philosophy: In our opinion, well-written library + code should keep its "debugging" code, and just normally have it turned off + by the compiler so as not to interfere with performance. This serves + several purposes: + + (1) assertions act as comments to the reader, telling you what the code + expects at that point. All assertions will always be true (unless + there really is a bug, of course). + + (2) leaving in the scaffolding code assists anyone who would like to modify + the code, or understand the algorithm (by reading the debugging output, + one can get a glimpse into what the code is doing). + + (3) (gasp!) for actually finding bugs. This code has been heavily tested + and "should" be fully functional and bug-free ... but you never know... + + To enable debugging, comment out the "#define NDEBUG" above. For a MATLAB + mexFunction, you will also need to modify mexopts.sh to remove the -DNDEBUG + definition. The code will become outrageously slow when debugging is + enabled. To control the level of debugging output, set an environment + variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, + you should see the following message on the standard output: + + colamd: debug version, D = 1 (THIS WILL BE SLOW!) + + or a similar message for symamd. If you don't, then debugging has not + been enabled. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +/* ------------------ */ +/* modified for UMFPACK: */ +#include "umf_internal.h" +#include "umf_colamd.h" +#include "umf_apply_order.h" +#include "umf_fsize.h" +/* ------------------ */ + +/* ========================================================================== */ +/* === Definitions ========================================================== */ +/* ========================================================================== */ + +/* ------------------ */ +/* UMFPACK: duplicate definitions moved to umf_internal.h */ +/* ------------------ */ + +/* Row and column status */ +#define ALIVE (0) +#define DEAD (-1) + +/* Column status */ +#define DEAD_PRINCIPAL (-1) +#define DEAD_NON_PRINCIPAL (-2) + +/* Macros for row and column status update and checking. */ +#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) +#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) +#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) +#define COL_IS_DEAD(c) (Col [c].start < ALIVE) +#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) +#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) +#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } +#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } +#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } + +/* ------------------ */ +/* UMFPACK: Colamd reporting mechanism moved to umf_internal.h */ +/* ------------------ */ + +/* ========================================================================== */ +/* === Prototypes of PRIVATE routines ======================================= */ +/* ========================================================================== */ + +PRIVATE Int init_rows_cols +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int p [] + /* Int stats [COLAMD_STATS] */ +) ; + +PRIVATE void init_scoring +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + double knobs [COLAMD_KNOBS], + Int *p_n_row2, + Int *p_n_col2, + Int *p_max_deg + /* ------------------ */ + /* added for UMFPACK */ + , Int *p_ndense_row /* number of dense rows */ + , Int *p_nempty_row /* number of original empty rows */ + , Int *p_nnewlyempty_row /* number of newly empty rows */ + , Int *p_ndense_col /* number of dense cols (excl "empty" cols) */ + , Int *p_nempty_col /* number of original empty cols */ + , Int *p_nnewlyempty_col /* number of newly empty cols */ +) ; + +PRIVATE Int find_ordering +( + Int n_row, + Int n_col, + Int Alen, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + Int n_col2, + Int max_deg, + Int pfree + /* ------------------ */ + /* added for UMFPACK: */ + , Int Front_npivcol [ ] + , Int Front_nrows [ ] + , Int Front_ncols [ ] + , Int Front_parent [ ] + , Int Front_cols [ ] + , Int *p_nfr + , Int aggressive + , Int InFront [ ] + /* ------------------ */ +) ; + +/* ------------------ */ +/* order_children deleted for UMFPACK: */ +/* ------------------ */ + +PRIVATE void detect_super_cols +( + +#ifndef NDEBUG + Int n_col, + Colamd_Row Row [], +#endif /* NDEBUG */ + + Colamd_Col Col [], + Int A [], + Int head [], + Int row_start, + Int row_length +) ; + +PRIVATE Int garbage_collection +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int *pfree +) ; + +PRIVATE Int clear_mark +( + Int n_row, + Colamd_Row Row [] +) ; + +/* ------------------ */ +/* print_report deleted for UMFPACK */ +/* ------------------ */ + +/* ========================================================================== */ +/* === Debugging prototypes and definitions ================================= */ +/* ========================================================================== */ + +#ifndef NDEBUG + +/* ------------------ */ +/* debugging macros moved for UMFPACK */ +/* ------------------ */ + +PRIVATE void debug_deg_lists +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) ; + +PRIVATE void debug_mark +( + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) ; + +PRIVATE void debug_matrix +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) ; + +PRIVATE void debug_structures +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) ; + +/* ------------------ */ +/* dump_super added for UMFPACK: */ +PRIVATE void dump_super +( + Int super_c, + Colamd_Col Col [], + Int n_col +) ; +/* ------------------ */ + +#endif /* NDEBUG */ + +/* ========================================================================== */ + + + +/* ========================================================================== */ +/* === USER-CALLABLE ROUTINES: ============================================== */ +/* ========================================================================== */ + + +/* ========================================================================== */ +/* === colamd_set_defaults ================================================== */ +/* ========================================================================== */ + +/* + The colamd_set_defaults routine sets the default values of the user- + controllable parameters for colamd: + + knobs [0] rows with knobs[0]*n_col entries or more are removed + prior to ordering in colamd. Rows and columns with + knobs[0]*n_col entries or more are removed prior to + ordering in symamd and placed last in the output + ordering. + + knobs [1] columns with knobs[1]*n_row entries or more are removed + prior to ordering in colamd, and placed last in the + column permutation. Symamd ignores this knob. + + knobs [2] if nonzero, then perform aggressive absorption. + + knobs [3..19] unused, but future versions might use this +*/ + +GLOBAL void UMF_colamd_set_defaults +( + /* === Parameters ======================================================= */ + + double knobs [COLAMD_KNOBS] /* knob array */ +) +{ + /* === Local variables ================================================== */ + + Int i ; + +#if 0 + if (!knobs) + { + return ; /* UMFPACK always passes knobs array */ + } +#endif + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + knobs [i] = 0 ; + } + knobs [COLAMD_DENSE_ROW] = 0.2 ; /* default changed for UMFPACK */ + knobs [COLAMD_DENSE_COL] = 0.2 ; /* default changed for UMFPACK */ + knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default is to do aggressive + * absorption */ +} + + +/* ========================================================================== */ +/* === symamd removed for UMFPACK =========================================== */ +/* ========================================================================== */ + + + +/* ========================================================================== */ +/* === colamd =============================================================== */ +/* ========================================================================== */ + +/* + The colamd routine computes a column ordering Q of a sparse matrix + A such that the LU factorization P(AQ) = LU remains sparse, where P is + selected via partial pivoting. The routine can also be viewed as + providing a permutation Q such that the Cholesky factorization + (AQ)'(AQ) = LL' remains sparse. +*/ + +/* For UMFPACK: colamd always returns TRUE */ + +GLOBAL Int UMF_colamd /* returns TRUE if successful, FALSE otherwise*/ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows in A */ + Int n_col, /* number of columns in A */ + Int Alen, /* length of A */ + Int A [], /* row indices of A */ + Int p [], /* pointers to columns in A */ + double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ + Int stats [COLAMD_STATS] /* output statistics and error codes */ + + /* ------------------ */ + /* added for UMFPACK: each Front_ array is of size n_col+1 */ + , Int Front_npivcol [ ] /* # pivot cols in each front */ + , Int Front_nrows [ ] /* # of rows in each front (incl. pivot rows) */ + , Int Front_ncols [ ] /* # of cols in each front (incl. pivot cols) */ + , Int Front_parent [ ] /* parent of each front */ + , Int Front_cols [ ] /* link list of pivot columns for each front */ + , Int *p_nfr /* total number of frontal matrices */ + , Int InFront [ ] /* InFront [row] = f if the original row was + * absorbed into front f. EMPTY if the row was + * empty, dense, or not absorbed. This array + * has size n_row+1 */ + /* ------------------ */ +) +{ + /* === Local variables ================================================== */ + + Int row ; /* row index */ + Int i ; /* loop index */ + Int nnz ; /* nonzeros in A */ + Int Row_size ; /* size of Row [], in integers */ + Int Col_size ; /* size of Col [], in integers */ +#if 0 + Int need ; /* minimum required length of A */ +#endif + Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ + Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int ngarbage ; /* number of garbage collections performed */ + Int max_deg ; /* maximum row degree */ + Int aggressive ; /* TRUE if doing aggressive absorption */ +#if 0 + double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ +#endif + + /* ------------------ */ + /* debugging initializations moved for UMFPACK */ + /* ------------------ */ + + /* ------------------ */ + /* added for UMFPACK: */ + Int ndense_row, nempty_row, parent, ndense_col, + nempty_col, k, col, nfr, *Front_child, *Front_sibling, *Front_stack, + *Front_order, *Front_size ; + Int nnewlyempty_col, nnewlyempty_row ; + /* ------------------ */ + + /* === Check the input arguments ======================================== */ + +#if 0 + if (!stats) + { + DEBUG0 (("colamd: stats not present\n")) ; + return (FALSE) ; /* UMFPACK: always passes stats [ ] */ + } +#endif + + ASSERT (stats != (Int *) NULL) ; + + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + +#if 0 + if (!A) /* A is not present */ + { + /* UMFPACK: always passes A [ ] */ + DEBUG0 (("colamd: A not present\n")) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + /* UMFPACK: always passes p [ ] */ + DEBUG0 (("colamd: p not present\n")) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + return (FALSE) ; + } + + if (n_row < 0) /* n_row must be >= 0 */ + { + /* UMFPACK: does not call UMF_colamd if n <= 0 */ + DEBUG0 (("colamd: nrow negative "ID"\n", n_row)) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ; + stats [COLAMD_INFO1] = n_row ; + return (FALSE) ; + } + + if (n_col < 0) /* n_col must be >= 0 */ + { + /* UMFPACK: does not call UMF_colamd if n <= 0 */ + DEBUG0 (("colamd: ncol negative "ID"\n", n_col)) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n_col ; + return (FALSE) ; + } +#endif + + ASSERT (A != (Int *) NULL) ; + ASSERT (p != (Int *) NULL) ; + ASSERT (n_row >= 0) ; + ASSERT (n_col >= 0) ; + + nnz = p [n_col] ; + +#if 0 + if (nnz < 0) /* nnz must be >= 0 */ + { + /* UMFPACK: does not call UMF_colamd if nnz < 0 */ + DEBUG0 (("colamd: number of entries negative "ID"\n", nnz)) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + return (FALSE) ; + } + + if (p [0] != 0) /* p [0] must be exactly zero */ + { + DEBUG0 (("colamd: p[0] not zero "ID"\n", p [0])) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + return (FALSE) ; + } +#endif + + ASSERT (nnz >= 0) ; + ASSERT (p [0] == 0) ; + + /* === If no knobs, set default knobs =================================== */ + +#if 0 + if (!knobs) + { + /* UMFPACK: always passes the knobs */ + UMF_colamd_set_defaults (default_knobs) ; + knobs = default_knobs ; + } +#endif + + ASSERT (knobs != (double *) NULL) ; + + /* --------------------- */ + /* added for UMFPACK v4.1: */ + aggressive = (knobs [COLAMD_AGGRESSIVE] != 0) ; + /* --------------------- */ + + /* === Allocate the Row and Col arrays from array A ===================== */ + + Col_size = UMF_COLAMD_C (n_col) ; + Row_size = UMF_COLAMD_R (n_row) ; + +#if 0 + need = MAX (2*nnz, 4*n_col) + n_col + Col_size + Row_size ; + if (need > Alen) + { + /* UMFPACK: always passes enough space */ + /* not enough space in array A to perform the ordering */ + DEBUG0 (("colamd: Need Alen >= "ID", given only Alen = "ID"\n", + need, Alen)) ; + stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ; + stats [COLAMD_INFO1] = need ; + stats [COLAMD_INFO2] = Alen ; + return (FALSE) ; + } +#endif + + Alen -= Col_size + Row_size ; + Col = (Colamd_Col *) &A [Alen] ; + Row = (Colamd_Row *) &A [Alen + Col_size] ; + + /* Size of A is now Alen >= MAX (2*nnz, 4*n_col) + n_col. The ordering + * requires Alen >= 2*nnz + n_col, and the postorder requires + * Alen >= 5*n_col. */ + + /* === Construct the row and column data structures ===================== */ + + i = init_rows_cols (n_row, n_col, Row, Col, A, p) ; + +#if 0 + if (!i) + { + /* input matrix is invalid */ + DEBUG0 (("colamd: Matrix invalid\n")) ; + return (FALSE) ; + } +#endif + + ASSERT (i) ; + + /* === UMFPACK: Initialize front info =================================== */ + + for (col = 0 ; col < n_col ; col++) + { + Front_npivcol [col] = 0 ; + Front_nrows [col] = 0 ; + Front_ncols [col] = 0 ; + Front_parent [col] = EMPTY ; + Front_cols [col] = EMPTY ; + } + + /* === Initialize scores, kill dense rows/columns ======================= */ + + init_scoring (n_row, n_col, Row, Col, A, p, knobs, + &n_row2, &n_col2, &max_deg + /* ------------------ */ + /* added for UMFPACK: */ + , &ndense_row, &nempty_row, &nnewlyempty_row + , &ndense_col, &nempty_col, &nnewlyempty_col + /* ------------------ */ + ) ; + ASSERT (n_row2 == n_row - nempty_row - nnewlyempty_row - ndense_row) ; + ASSERT (n_col2 == n_col - nempty_col - nnewlyempty_col - ndense_col) ; + + /* === Order the supercolumns =========================================== */ + + ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, + n_col2, max_deg, 2*nnz + /* ------------------ */ + /* added for UMFPACK: */ + , Front_npivcol, Front_nrows, Front_ncols, Front_parent, Front_cols + , &nfr, aggressive, InFront + /* ------------------ */ + ) ; + + /* ------------------ */ + /* changed for UMFPACK: */ + + /* A is no longer needed, so use A [0..5*nfr-1] as workspace [ [ */ + /* This step requires Alen >= 5*n_col */ + Front_child = A ; + Front_sibling = Front_child + nfr ; + Front_stack = Front_sibling + nfr ; + Front_order = Front_stack + nfr ; + Front_size = Front_order + nfr ; + + UMF_fsize (nfr, Front_size, Front_nrows, Front_ncols, + Front_parent, Front_npivcol) ; + + AMD_postorder (nfr, Front_parent, Front_npivcol, Front_size, + Front_order, Front_child, Front_sibling, Front_stack) ; + + /* Front_size, Front_stack, Front_child, Front_sibling no longer needed ] */ + + /* use A [0..nfr-1] as workspace */ + UMF_apply_order (Front_npivcol, Front_order, A, nfr, nfr) ; + UMF_apply_order (Front_nrows, Front_order, A, nfr, nfr) ; + UMF_apply_order (Front_ncols, Front_order, A, nfr, nfr) ; + UMF_apply_order (Front_parent, Front_order, A, nfr, nfr) ; + UMF_apply_order (Front_cols, Front_order, A, nfr, nfr) ; + + /* fix the parent to refer to the new numbering */ + for (i = 0 ; i < nfr ; i++) + { + parent = Front_parent [i] ; + if (parent != EMPTY) + { + Front_parent [i] = Front_order [parent] ; + } + } + + /* fix InFront to refer to the new numbering */ + for (row = 0 ; row < n_row ; row++) + { + i = InFront [row] ; + ASSERT (i >= EMPTY && i < nfr) ; + if (i != EMPTY) + { + InFront [row] = Front_order [i] ; + } + } + + /* Front_order longer needed ] */ + + /* === Order the columns in the fronts ================================== */ + + /* use A [0..n_col-1] as inverse permutation */ + for (i = 0 ; i < n_col ; i++) + { + A [i] = EMPTY ; + } + k = 0 ; + for (i = 0 ; i < nfr ; i++) + { + ASSERT (Front_npivcol [i] > 0) ; + for (col = Front_cols [i] ; col != EMPTY ; col = Col [col].nextcol) + { + ASSERT (col >= 0 && col < n_col) ; + DEBUG1 (("Colamd output ordering: k "ID" col "ID"\n", k, col)) ; + p [k] = col ; + ASSERT (A [col] == EMPTY) ; + A [col] = k ; + k++ ; + } + } + + /* === Order the "dense" and null columns =============================== */ + + ASSERT (k == n_col2) ; + if (n_col2 < n_col) + { + for (col = 0 ; col < n_col ; col++) + { + if (A [col] == EMPTY) + { + k = Col [col].shared2.order ; + ASSERT (k >= n_col2 && k < n_col) ; + DEBUG1 (("Colamd output ordering: k "ID" col "ID + " (dense or null col)\n", k, col)) ; + p [k] = col ; + A [col] = k ; + } + } + } + + /* ------------------ */ + + /* === Return statistics in stats ======================================= */ + + /* ------------------ */ + /* modified for UMFPACK */ + stats [COLAMD_DENSE_ROW] = ndense_row ; + stats [COLAMD_EMPTY_ROW] = nempty_row ; + stats [COLAMD_NEWLY_EMPTY_ROW] = nnewlyempty_row ; + stats [COLAMD_DENSE_COL] = ndense_col ; + stats [COLAMD_EMPTY_COL] = nempty_col ; + stats [COLAMD_NEWLY_EMPTY_COL] = nnewlyempty_col ; + ASSERT (ndense_col + nempty_col + nnewlyempty_col == n_col - n_col2) ; + /* ------------------ */ + stats [COLAMD_DEFRAG_COUNT] = ngarbage ; + *p_nfr = nfr ; + DEBUG1 (("colamd: done.\n")) ; + return (TRUE) ; +} + + + + +/* ========================================================================== */ +/* === colamd_report removed for UMFPACK ==================================== */ +/* ========================================================================== */ + +/* ========================================================================== */ +/* === symamd_report removed for UMFPACK ==================================== */ +/* ========================================================================== */ + + + +/* ========================================================================== */ +/* === NON-USER-CALLABLE ROUTINES: ========================================== */ +/* ========================================================================== */ + +/* There are no user-callable routines beyond this point in the file */ + + +/* ========================================================================== */ +/* === init_rows_cols ======================================================= */ +/* ========================================================================== */ + +/* + Takes the column form of the matrix in A and creates the row form of the + matrix. Also, row and column attributes are stored in the Col and Row + structs. If the columns are un-sorted or contain duplicate row indices, + this routine will also sort and remove duplicate row indices from the + column form of the matrix. Returns FALSE if the matrix is invalid, + TRUE otherwise. Not user-callable. +*/ + +/* For UMFPACK, this always returns TRUE */ + +PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A, of size Alen */ + Int p [] /* pointers to columns in A, of size n_col+1 */ +/* + Int stats [COLAMD_STATS] colamd statistics, removed for UMFPACK +*/ +) +{ + /* === Local variables ================================================== */ + + Int col ; /* a column index */ + Int row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int *cp_end ; /* a pointer to the end of a column */ + + /* === Initialize columns, and check column pointers ==================== */ + + for (col = 0 ; col < n_col ; col++) + { + Col [col].start = p [col] ; + Col [col].length = p [col+1] - p [col] ; + +#if 0 + if (Col [col].length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = Col [col].length ; + DEBUG0 (("colamd: col "ID" length "ID" <= 0\n", + col, Col [col].length)); + return (FALSE) ; + } +#endif + + ASSERT (Col [col].length >= 0) ; + + /* added for UMFPACK v4.1 */ + ASSERT (Col [col].length > 0) ; + + Col [col].shared1.thickness = 1 ; + Col [col].shared2.score = 0 ; + Col [col].shared3.prev = EMPTY ; + Col [col].shared4.degree_next = EMPTY ; + + /* ------------------ */ + /* added for UMFPACK: */ + Col [col].nextcol = EMPTY ; + Col [col].lastcol = col ; + /* ------------------ */ + } + + /* p [0..n_col] no longer needed, used as "head" in subsequent routines */ + + /* === Scan columns, compute row degrees, and check row indices ========= */ + + /* ------------------ */ + /* stats [COLAMD_INFO3] = 0 ; */ + /* number of duplicate or unsorted row indices - not computed in UMFPACK */ + /* ------------------ */ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].length = 0 ; + /* ------------------ */ + /* removed for UMFPACK */ + /* Row [row].shared2.mark = -1 ; */ + /* ------------------ */ + /* ------------------ */ + /* added for UMFPACK: */ + Row [row].thickness = 1 ; + Row [row].front = EMPTY ; + /* ------------------ */ + } + + for (col = 0 ; col < n_col ; col++) + { +#ifndef NDEBUG + Int last_row = -1 ; +#endif + + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + + while (cp < cp_end) + { + row = *cp++ ; + +#if 0 + /* make sure row indices within range */ + if (row < 0 || row >= n_row) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + /* ------------------ */ + /* not needed in UMFPACK: */ + /* stats [COLAMD_INFO3] = n_row ; */ + /* ------------------ */ + DEBUG0 (("colamd: row "ID" col "ID" out of bounds\n", row,col)); + return (FALSE) ; + } +#endif + + ASSERT (row >= 0 && row < n_row) ; + +#if 0 + /* ------------------ */ + /* changed for UMFPACK */ + if (row <= last_row) + { + /* row index are unsorted or repeated (or both), thus col */ + /* is jumbled. This is an error condition for UMFPACK */ + stats [COLAMD_STATUS] = COLAMD_ERROR_jumbled_matrix ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + DEBUG1 (("colamd: row "ID" col "ID" unsorted/duplicate\n", + row, col)) ; + return (FALSE) ; + } + /* ------------------ */ +#endif + + ASSERT (row > last_row) ; + + /* ------------------ */ + /* changed for UMFPACK - jumbled columns not tolerated */ + Row [row].length++ ; + /* ------------------ */ + +#ifndef NDEBUG + last_row = row ; +#endif + } + } + + /* === Compute row pointers ============================================= */ + + /* row form of the matrix starts directly after the column */ + /* form of matrix in A */ + Row [0].start = p [n_col] ; + Row [0].shared1.p = Row [0].start ; + /* ------------------ */ + /* removed for UMFPACK */ + /* Row [0].shared2.mark = -1 ; */ + /* ------------------ */ + for (row = 1 ; row < n_row ; row++) + { + Row [row].start = Row [row-1].start + Row [row-1].length ; + Row [row].shared1.p = Row [row].start ; + /* ------------------ */ + /* removed for UMFPACK */ + /* Row [row].shared2.mark = -1 ; */ + /* ------------------ */ + } + + /* === Create row form ================================================== */ + + /* ------------------ */ + /* jumbled matrix case removed for UMFPACK */ + /* ------------------ */ + + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + A [(Row [*cp++].shared1.p)++] = col ; + } + } + + /* === Clear the row marks and set row degrees ========================== */ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].shared2.mark = 0 ; + Row [row].shared1.degree = Row [row].length ; + } + + /* ------------------ */ + /* recreate columns for jumbled matrix case removed for UMFPACK */ + /* ------------------ */ + + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === init_scoring ========================================================= */ +/* ========================================================================== */ + +/* + Kills dense or empty columns and rows, calculates an initial score for + each column, and places all columns in the degree lists. Not user-callable. +*/ + +PRIVATE void init_scoring +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameters */ + Int *p_n_row2, /* number of non-dense, non-empty rows */ + Int *p_n_col2, /* number of non-dense, non-empty columns */ + Int *p_max_deg /* maximum row degree */ + /* ------------------ */ + /* added for UMFPACK */ + , Int *p_ndense_row /* number of dense rows */ + , Int *p_nempty_row /* number of original empty rows */ + , Int *p_nnewlyempty_row /* number of newly empty rows */ + , Int *p_ndense_col /* number of dense cols (excl "empty" cols) */ + , Int *p_nempty_col /* number of original empty cols */ + , Int *p_nnewlyempty_col /* number of newly empty cols */ + /* ------------------ */ +) +{ + /* === Local variables ================================================== */ + + Int c ; /* a column index */ + Int r, row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int deg ; /* degree of a row or column */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *new_cp ; /* new column pointer */ + Int col_length ; /* length of pruned column */ + Int score ; /* current column score */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int dense_row_count ; /* remove rows with more entries than this */ + Int dense_col_count ; /* remove cols with more entries than this */ + Int min_score ; /* smallest column score */ + Int max_deg ; /* maximum row degree */ + Int next_col ; /* Used to add to degree list.*/ + + /* ------------------ */ + /* added for UMFPACK */ + Int ndense_row ; /* number of dense rows */ + Int nempty_row ; /* number of empty rows */ + Int nnewlyempty_row ; /* number of newly empty rows */ + Int ndense_col ; /* number of dense cols (excl "empty" cols) */ + Int nempty_col ; /* number of original empty cols */ + Int nnewlyempty_col ; /* number of newly empty cols */ + Int ne ; + /* ------------------ */ + +#ifndef NDEBUG + Int debug_count ; /* debug only. */ +#endif /* NDEBUG */ + + /* === Extract knobs ==================================================== */ + + /* --------------------- */ + /* old dense row/column knobs: + dense_row_count = MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ; + dense_col_count = MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ; + */ + /* new, for UMFPACK: */ + /* Note: if knobs contains a NaN, this is undefined: */ + dense_row_count = + UMFPACK_DENSE_DEGREE_THRESHOLD (knobs [COLAMD_DENSE_ROW], n_col) ; + dense_col_count = + UMFPACK_DENSE_DEGREE_THRESHOLD (knobs [COLAMD_DENSE_COL], n_row) ; + /* Make sure dense_*_count is between 0 and n: */ + dense_row_count = MAX (0, MIN (dense_row_count, n_col)) ; + dense_col_count = MAX (0, MIN (dense_col_count, n_row)) ; + /* --------------------- */ + + DEBUG1 (("colamd: densecount: "ID" "ID"\n", + dense_row_count, dense_col_count)) ; + max_deg = 0 ; + n_col2 = n_col ; + n_row2 = n_row ; + + /* --------------------- */ + /* added for UMFPACK */ + ndense_col = 0 ; + nempty_col = 0 ; + nnewlyempty_col = 0 ; + ndense_row = 0 ; + nempty_row = 0 ; + nnewlyempty_row = 0 ; + /* --------------------- */ + + /* === Kill empty columns =============================================== */ + + /* removed for UMFPACK v4.1. prune_singletons has already removed empty + * columns and empty rows */ + +#if 0 + /* Put the empty columns at the end in their natural order, so that LU */ + /* factorization can proceed as far as possible. */ + for (c = n_col-1 ; c >= 0 ; c--) + { + deg = Col [c].length ; + if (deg == 0) + { + /* this is a empty column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + /* --------------------- */ + /* added for UMFPACK */ + nempty_col++ ; + /* --------------------- */ + } + } + DEBUG1 (("colamd: null columns killed: "ID"\n", n_col - n_col2)) ; +#endif + +#ifndef NDEBUG + for (c = 0 ; c < n_col ; c++) + { + ASSERT (Col [c].length > 0) ; + } +#endif + + /* === Count null rows ================================================== */ + +#if 0 + for (r = 0 ; r < n_row ; r++) + { + deg = Row [r].shared1.degree ; + if (deg == 0) + { + /* this is an original empty row */ + nempty_row++ ; + } + } +#endif + +#ifndef NDEBUG + for (r = 0 ; r < n_row ; r++) + { + ASSERT (Row [r].shared1.degree > 0) ; + ASSERT (Row [r].length > 0) ; + } +#endif + + /* === Kill dense columns =============================================== */ + + /* Put the dense columns at the end, in their natural order */ + for (c = n_col-1 ; c >= 0 ; c--) + { + + /* ----------------------------------------------------------------- */ +#if 0 + /* removed for UMFPACK v4.1: no empty columns */ + /* skip any dead columns */ + if (COL_IS_DEAD (c)) + { + continue ; + } +#endif + ASSERT (COL_IS_ALIVE (c)) ; + ASSERT (Col [c].length > 0) ; + /* ----------------------------------------------------------------- */ + + deg = Col [c].length ; + if (deg > dense_col_count) + { + /* this is a dense column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + /* --------------------- */ + /* added for UMFPACK */ + ndense_col++ ; + /* --------------------- */ + /* decrement the row degrees */ + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + Row [*cp++].shared1.degree-- ; + } + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: Dense and null columns killed: "ID"\n", n_col - n_col2)) ; + + /* === Kill dense and empty rows ======================================== */ + + /* Note that there can now be empty rows, since dense columns have + * been deleted. These are "newly" empty rows. */ + + ne = 0 ; + for (r = 0 ; r < n_row ; r++) + { + deg = Row [r].shared1.degree ; + ASSERT (deg >= 0 && deg <= n_col) ; + /* --------------------- */ + /* added for UMFPACK */ + if (deg > dense_row_count) + { + /* There is at least one dense row. Continue ordering, but */ + /* symbolic factorization will be redone after UMF_colamd is done.*/ + ndense_row++ ; + } + if (deg == 0) + { + /* this is a newly empty row, or original empty row */ + ne++ ; + } + /* --------------------- */ + if (deg > dense_row_count || deg == 0) + { + /* kill a dense or empty row */ + KILL_ROW (r) ; + /* --------------------- */ + /* added for UMFPACK */ + Row [r].thickness = 0 ; + /* --------------------- */ + --n_row2 ; + } + else + { + /* keep track of max degree of remaining rows */ + max_deg = MAX (max_deg, deg) ; + } + } + nnewlyempty_row = ne - nempty_row ; + DEBUG1 (("colamd: Dense rows killed: "ID"\n", ndense_row)) ; + DEBUG1 (("colamd: Dense and null rows killed: "ID"\n", n_row - n_row2)) ; + + /* === Compute initial column scores ==================================== */ + + /* At this point the row degrees are accurate. They reflect the number */ + /* of "live" (non-dense) columns in each row. No empty rows exist. */ + /* Some "live" columns may contain only dead rows, however. These are */ + /* pruned in the code below. */ + + /* now find the initial matlab score for each column */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip dead column */ + if (COL_IS_DEAD (c)) + { + continue ; + } + score = 0 ; + cp = &A [Col [c].start] ; + new_cp = cp ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + /* skip if dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + /* compact the column */ + *new_cp++ = row ; + /* add row's external degree */ + score += Row [row].shared1.degree - 1 ; + /* guard against integer overflow */ + score = MIN (score, n_col) ; + } + /* determine pruned column length */ + col_length = (Int) (new_cp - &A [Col [c].start]) ; + if (col_length == 0) + { + /* a newly-made null column (all rows in this col are "dense" */ + /* and have already been killed) */ + DEBUG2 (("Newly null killed: "ID"\n", c)) ; + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + /* --------------------- */ + /* added for UMFPACK */ + nnewlyempty_col++ ; + /* --------------------- */ + } + else + { + /* set column length and set score */ + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + Col [c].length = col_length ; + Col [c].shared2.score = score ; + } + } + DEBUG1 (("colamd: Dense, null, and newly-null columns killed: "ID"\n", + n_col-n_col2)) ; + + /* At this point, all empty rows and columns are dead. All live columns */ + /* are "clean" (containing no dead rows) and simplicial (no supercolumns */ + /* yet). Rows may contain dead columns, but all live rows contain at */ + /* least one live column. */ + +#ifndef NDEBUG + debug_structures (n_row, n_col, Row, Col, A, n_col2) ; +#endif /* NDEBUG */ + + /* === Initialize degree lists ========================================== */ + +#ifndef NDEBUG + debug_count = 0 ; +#endif /* NDEBUG */ + + /* clear the hash buckets */ + for (c = 0 ; c <= n_col ; c++) + { + head [c] = EMPTY ; + } + min_score = n_col ; + /* place in reverse order, so low column indices are at the front */ + /* of the lists. This is to encourage natural tie-breaking */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* only add principal columns to degree lists */ + if (COL_IS_ALIVE (c)) + { + DEBUG4 (("place "ID" score "ID" minscore "ID" ncol "ID"\n", + c, Col [c].shared2.score, min_score, n_col)) ; + + /* === Add columns score to DList =============================== */ + + score = Col [c].shared2.score ; + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + ASSERT (head [score] >= EMPTY) ; + + /* now add this column to dList at proper score location */ + next_col = head [score] ; + Col [c].shared3.prev = EMPTY ; + Col [c].shared4.degree_next = next_col ; + + /* if there already was a column with the same score, set its */ + /* previous pointer to this new column */ + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = c ; + } + head [score] = c ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, score) ; + +#ifndef NDEBUG + debug_count++ ; +#endif /* NDEBUG */ + + } + } + +#ifndef NDEBUG + DEBUG1 (("colamd: Live cols "ID" out of "ID", non-princ: "ID"\n", + debug_count, n_col, n_col-debug_count)) ; + ASSERT (debug_count == n_col2) ; + debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ; +#endif /* NDEBUG */ + + /* === Return number of remaining columns, and max row degree =========== */ + + *p_n_col2 = n_col2 ; + *p_n_row2 = n_row2 ; + *p_max_deg = max_deg ; + + /* --------------------- */ + /* added for UMFPACK */ + *p_ndense_row = ndense_row ; + *p_nempty_row = nempty_row ; /* original empty rows */ + *p_nnewlyempty_row = nnewlyempty_row ; + *p_ndense_col = ndense_col ; + *p_nempty_col = nempty_col ; /* original empty cols */ + *p_nnewlyempty_col = nnewlyempty_col ; + /* --------------------- */ +} + + +/* ========================================================================== */ +/* === find_ordering ======================================================== */ +/* ========================================================================== */ + +/* + Order the principal columns of the supercolumn form of the matrix + (no supercolumns on input). Uses a minimum approximate column minimum + degree ordering method. Not user-callable. +*/ + +PRIVATE Int find_ordering /* return the number of garbage collections */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Int Alen, /* size of A, 2*nnz + n_col or larger */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + Int n_col2, /* Remaining columns to order */ + Int max_deg, /* Maximum row degree */ + Int pfree /* index of first free slot (2*nnz on entry) */ + /* ------------------ */ + /* added for UMFPACK: */ + , Int Front_npivcol [ ] + , Int Front_nrows [ ] + , Int Front_ncols [ ] + , Int Front_parent [ ] + , Int Front_cols [ ] + , Int *p_nfr /* number of fronts */ + , Int aggressive + , Int InFront [ ] + /* ------------------ */ +) +{ + /* === Local variables ================================================== */ + + Int k ; /* current pivot ordering step */ + Int pivot_col ; /* current pivot column */ + Int *cp ; /* a column pointer */ + Int *rp ; /* a row pointer */ + Int pivot_row ; /* current pivot row */ + Int *new_cp ; /* modified column pointer */ + Int *new_rp ; /* modified row pointer */ + Int pivot_row_start ; /* pointer to start of pivot row */ + Int pivot_row_degree ; /* number of columns in pivot row */ + Int pivot_row_length ; /* number of supercolumns in pivot row */ + Int pivot_col_score ; /* score of pivot column */ + Int needed_memory ; /* free space needed for pivot row */ + Int *cp_end ; /* pointer to the end of a column */ + Int *rp_end ; /* pointer to the end of a row */ + Int row ; /* a row index */ + Int col ; /* a column index */ + Int max_score ; /* maximum possible score */ + Int cur_score ; /* score of current column */ + unsigned Int hash ; /* hash value for supernode detection */ + Int head_column ; /* head of hash bucket */ + Int first_col ; /* first column in hash bucket */ + Int tag_mark ; /* marker value for mark array */ + Int row_mark ; /* Row [row].shared2.mark */ + Int set_difference ; /* set difference size of row with pivot row */ + Int min_score ; /* smallest column score */ + Int col_thickness ; /* "thickness" (no. of columns in a supercol) */ + Int max_mark ; /* maximum value of tag_mark */ + Int pivot_col_thickness ; /* number of columns represented by pivot col */ + Int prev_col ; /* Used by Dlist operations. */ + Int next_col ; /* Used by Dlist operations. */ + Int ngarbage ; /* number of garbage collections performed */ + +#ifndef NDEBUG + Int debug_d ; /* debug loop counter */ + Int debug_step = 0 ; /* debug loop counter */ +#endif /* NDEBUG */ + + /* ------------------ */ + /* added for UMFPACK: */ + Int pivot_row_thickness ; /* number of rows represented by pivot row */ + Int nfr = 0 ; /* number of fronts */ + Int child ; + /* ------------------ */ + + /* === Initialization and clear mark ==================================== */ + + max_mark = MAX_MARK (n_col) ; /* defined in umfpack.h */ + tag_mark = clear_mark (n_row, Row) ; + min_score = 0 ; + ngarbage = 0 ; + DEBUG1 (("colamd: Ordering, n_col2="ID"\n", n_col2)) ; + + for (row = 0 ; row < n_row ; row++) + { + InFront [row] = EMPTY ; + } + + /* === Order the columns ================================================ */ + + for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */) + { + +#ifndef NDEBUG + if (debug_step % 100 == 0) + { + DEBUG2 (("\n... Step k: "ID" out of n_col2: "ID"\n", k, n_col2)) ; + } + else + { + DEBUG3 (("\n-----Step k: "ID" out of n_col2: "ID"\n", k, n_col2)) ; + } + debug_step++ ; + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + + /* === Select pivot column, and order it ============================ */ + + /* make sure degree list isn't empty */ + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (head [min_score] >= EMPTY) ; + +#ifndef NDEBUG + for (debug_d = 0 ; debug_d < min_score ; debug_d++) + { + ASSERT (head [debug_d] == EMPTY) ; + } +#endif /* NDEBUG */ + + /* get pivot column from head of minimum degree list */ + while (head [min_score] == EMPTY && min_score < n_col) + { + min_score++ ; + } + pivot_col = head [min_score] ; + ASSERT (pivot_col >= 0 && pivot_col <= n_col) ; + next_col = Col [pivot_col].shared4.degree_next ; + head [min_score] = next_col ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = EMPTY ; + } + + ASSERT (COL_IS_ALIVE (pivot_col)) ; + DEBUG3 (("Pivot col: "ID"\n", pivot_col)) ; + + /* remember score for defrag check */ + pivot_col_score = Col [pivot_col].shared2.score ; + + /* the pivot column is the kth column in the pivot order */ + Col [pivot_col].shared2.order = k ; + + /* increment order count by column thickness */ + pivot_col_thickness = Col [pivot_col].shared1.thickness ; + /* ------------------ */ + /* changed for UMFPACK: */ + k += pivot_col_thickness ; + /* ------------------ */ + ASSERT (pivot_col_thickness > 0) ; + + /* === Garbage_collection, if necessary ============================= */ + + needed_memory = MIN (pivot_col_score, n_col - k) ; + if (pfree + needed_memory >= Alen) + { + pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; + ngarbage++ ; + /* after garbage collection we will have enough */ + ASSERT (pfree + needed_memory < Alen) ; + /* garbage collection has wiped out the Row[].shared2.mark array */ + tag_mark = clear_mark (n_row, Row) ; + +#ifndef NDEBUG + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + } + + /* === Compute pivot row pattern ==================================== */ + + /* get starting location for this new merged row */ + pivot_row_start = pfree ; + + /* initialize new row counts to zero */ + pivot_row_degree = 0 ; + + /* ------------------ */ + /* added for UMFPACK: */ + pivot_row_thickness = 0 ; + /* ------------------ */ + + /* [ tag pivot column as having been visited so it isn't included */ + /* in merged pivot row */ + Col [pivot_col].shared1.thickness = -pivot_col_thickness ; + + /* pivot row is the union of all rows in the pivot column pattern */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + DEBUG4 (("Pivot col pattern %d "ID"\n", ROW_IS_ALIVE(row), row)) ; + /* skip if row is dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + + /* ------------------ */ + /* added for UMFPACK: */ + /* sum the thicknesses of all the rows */ + /* ASSERT (Row [row].thickness > 0) ; */ + pivot_row_thickness += Row [row].thickness ; + /* ------------------ */ + + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + /* add the column, if alive and untagged */ + col_thickness = Col [col].shared1.thickness ; + if (col_thickness > 0 && COL_IS_ALIVE (col)) + { + /* tag column in pivot row */ + Col [col].shared1.thickness = -col_thickness ; + ASSERT (pfree < Alen) ; + /* place column in pivot row */ + A [pfree++] = col ; + pivot_row_degree += col_thickness ; + /* ------------------ */ + /* added for UMFPACK: */ + DEBUG4 (("\t\t\tNew live column in pivot row: "ID"\n",col)); + /* ------------------ */ + } + /* ------------------ */ + /* added for UMFPACK */ +#ifndef NDEBUG + if (col_thickness < 0 && COL_IS_ALIVE (col)) + { + DEBUG4 (("\t\t\tOld live column in pivot row: "ID"\n",col)); + } +#endif + /* ------------------ */ + } + } + + /* ------------------ */ + /* added for UMFPACK: */ + /* pivot_row_thickness is the number of rows in frontal matrix */ + /* both pivotal rows and nonpivotal rows */ + /* ------------------ */ + + /* clear tag on pivot column */ + Col [pivot_col].shared1.thickness = pivot_col_thickness ; /* ] */ + max_deg = MAX (max_deg, pivot_row_degree) ; + +#ifndef NDEBUG + DEBUG3 (("check2\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Kill all rows used to construct pivot row ==================== */ + + /* also kill pivot row, temporarily */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* may be killing an already dead row */ + row = *cp++ ; + + DEBUG2 (("Kill row in pivot col: "ID" alive? %d, front "ID"\n", + row, ROW_IS_ALIVE (row), Row [row].front)) ; + + /* added for UMFPACK: */ + if (ROW_IS_ALIVE (row)) + { + if (Row [row].front != EMPTY) + { + /* This row represents a frontal matrix. */ + /* Row [row].front is a child of current front */ + child = Row [row].front ; + Front_parent [child] = nfr ; + DEBUG1 (("Front "ID" => front "ID", normal\n", child, nfr)); + } + else + { + /* This is an original row. Keep track of which front + * is its parent in the row-merge tree. */ + InFront [row] = nfr ; + DEBUG1 (("Row "ID" => front "ID", normal\n", row, nfr)) ; + } + } + + KILL_ROW (row) ; + + /* ------------------ */ + /* added for UMFPACK: */ + Row [row].thickness = 0 ; + /* ------------------ */ + } + + /* === Select a row index to use as the new pivot row =============== */ + + pivot_row_length = pfree - pivot_row_start ; + if (pivot_row_length > 0) + { + /* pick the "pivot" row arbitrarily (first row in col) */ + pivot_row = A [Col [pivot_col].start] ; + DEBUG3 (("Pivotal row is "ID"\n", pivot_row)) ; + } + else + { + /* there is no pivot row, since it is of zero length */ + pivot_row = EMPTY ; + ASSERT (pivot_row_length == 0) ; + } + ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ; + + /* === Approximate degree computation =============================== */ + + /* Here begins the computation of the approximate degree. The column */ + /* score is the sum of the pivot row "length", plus the size of the */ + /* set differences of each row in the column minus the pattern of the */ + /* pivot row itself. The column ("thickness") itself is also */ + /* excluded from the column score (we thus use an approximate */ + /* external degree). */ + + /* The time taken by the following code (compute set differences, and */ + /* add them up) is proportional to the size of the data structure */ + /* being scanned - that is, the sum of the sizes of each column in */ + /* the pivot row. Thus, the amortized time to compute a column score */ + /* is proportional to the size of that column (where size, in this */ + /* context, is the column "length", or the number of row indices */ + /* in that column). The number of row indices in a column is */ + /* monotonically non-decreasing, from the length of the original */ + /* column on input to colamd. */ + + /* === Compute set differences ====================================== */ + + DEBUG3 (("** Computing set differences phase. **\n")) ; + + /* pivot row is currently dead - it will be revived later. */ + + DEBUG3 (("Pivot row: \n")) ; + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + DEBUG3 ((" Col: "ID"\n", col)) ; + + /* clear tags used to construct pivot row pattern */ + col_thickness = -Col [col].shared1.thickness ; + ASSERT (col_thickness > 0) ; + Col [col].shared1.thickness = col_thickness ; + + /* === Remove column from degree list =========================== */ + + cur_score = Col [col].shared2.score ; + prev_col = Col [col].shared3.prev ; + next_col = Col [col].shared4.degree_next ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (cur_score >= EMPTY) ; + if (prev_col == EMPTY) + { + head [cur_score] = next_col ; + } + else + { + Col [prev_col].shared4.degree_next = next_col ; + } + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = prev_col ; + } + + /* === Scan the column ========================================== */ + + cp = &A [Col [col].start] ; + cp_end = cp + Col [col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + continue ; + } + ASSERT (row != pivot_row) ; + set_difference = row_mark - tag_mark ; + /* check if the row has been seen yet */ + if (set_difference < 0) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + set_difference = Row [row].shared1.degree ; + } + /* subtract column thickness from this row's set difference */ + set_difference -= col_thickness ; + ASSERT (set_difference >= 0) ; + ASSERT (ROW_IS_ALIVE (row)) ; + + /* absorb this row if the set difference becomes zero */ + if (set_difference == 0 && aggressive) + { + /* v4.1: do aggressive absorption */ + DEBUG3 (("aggressive absorption. Row: "ID"\n", row)) ; + + if (Row [row].front != EMPTY) + { + /* Row [row].front is a child of current front. */ + child = Row [row].front ; + Front_parent [child] = nfr ; + DEBUG1 (("Front "ID" => front "ID", aggressive\n", + child, nfr)) ; + } + else + { + /* this is an original row. Keep track of which front + * assembles it, for the row-merge tree */ + InFront [row] = nfr ; + DEBUG1 (("Row "ID" => front "ID", aggressive\n", + row, nfr)) ; + } + + KILL_ROW (row) ; + + /* sum the thicknesses of all the rows */ + /* ASSERT (Row [row].thickness > 0) ; */ + pivot_row_thickness += Row [row].thickness ; + Row [row].thickness = 0 ; + + } + else + { + /* save the new mark */ + Row [row].shared2.mark = set_difference + tag_mark ; + } + } + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k-pivot_row_degree, max_deg) ; +#endif /* NDEBUG */ + + /* === Add up set differences for each column ======================= */ + + DEBUG3 (("** Adding set differences phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + hash = 0 ; + cur_score = 0 ; + cp = &A [Col [col].start] ; + /* compact the column */ + new_cp = cp ; + cp_end = cp + Col [col].length ; + + DEBUG4 (("Adding set diffs for Col: "ID".\n", col)) ; + + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + ASSERT(row >= 0 && row < n_row) ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + /* ------------------ */ + /* changed for UMFPACK: */ + DEBUG4 ((" Row "ID", dead\n", row)) ; + /* ------------------ */ + continue ; + } + /* ------------------ */ + /* changed for UMFPACK: */ + /* ASSERT (row_mark > tag_mark) ; */ + DEBUG4 ((" Row "ID", set diff "ID"\n", row, row_mark-tag_mark)); + ASSERT (row_mark >= tag_mark) ; + /* ------------------ */ + /* compact the column */ + *new_cp++ = row ; + /* compute hash function */ + hash += row ; + /* add set difference */ + cur_score += row_mark - tag_mark ; + /* integer overflow... */ + cur_score = MIN (cur_score, n_col) ; + } + + /* recompute the column's length */ + Col [col].length = (Int) (new_cp - &A [Col [col].start]) ; + + /* === Further mass elimination ================================= */ + + if (Col [col].length == 0) + { + DEBUG4 (("further mass elimination. Col: "ID"\n", col)) ; + /* nothing left but the pivot row in this column */ + KILL_PRINCIPAL_COL (col) ; + pivot_row_degree -= Col [col].shared1.thickness ; + ASSERT (pivot_row_degree >= 0) ; + /* order it */ + Col [col].shared2.order = k ; + /* increment order count by column thickness */ + k += Col [col].shared1.thickness ; + + /* ------------------ */ + /* added for UMFPACK: */ + pivot_col_thickness += Col [col].shared1.thickness ; + + /* add to column list of front ... */ +#ifndef NDEBUG + DEBUG1 (("Mass")) ; + dump_super (col, Col, n_col) ; +#endif + Col [Col [col].lastcol].nextcol = Front_cols [nfr] ; + Front_cols [nfr] = col ; + /* ------------------ */ + + } + else + { + /* === Prepare for supercolumn detection ==================== */ + + DEBUG4 (("Preparing supercol detection for Col: "ID".\n", col)); + + /* save score so far */ + Col [col].shared2.score = cur_score ; + + /* add column to hash table, for supercolumn detection */ + /* NOTE: hash is an unsigned Int to avoid a problem in ANSI C. + * The sign of the expression a % b is not defined when a and/or + * b are negative. Since hash is unsigned and n_col >= 0, + * this problem is avoided. */ + hash %= n_col + 1 ; + + DEBUG4 ((" Hash = "ID", n_col = "ID".\n", (Int) hash, n_col)) ; + ASSERT (((Int) hash) <= n_col) ; + + head_column = head [hash] ; + if (head_column > EMPTY) + { + /* degree list "hash" is non-empty, use prev (shared3) of */ + /* first column in degree list as head of hash bucket */ + first_col = Col [head_column].shared3.headhash ; + Col [head_column].shared3.headhash = col ; + } + else + { + /* degree list "hash" is empty, use head as hash bucket */ + first_col = - (head_column + 2) ; + head [hash] = - (col + 2) ; + } + Col [col].shared4.hash_next = first_col ; + + /* save hash function in Col [col].shared3.hash */ + Col [col].shared3.hash = (Int) hash ; + ASSERT (COL_IS_ALIVE (col)) ; + } + } + + /* The approximate external column degree is now computed. */ + + /* === Supercolumn detection ======================================== */ + + DEBUG3 (("** Supercolumn detection phase. **\n")) ; + + detect_super_cols ( + +#ifndef NDEBUG + n_col, Row, +#endif /* NDEBUG */ + + Col, A, head, pivot_row_start, pivot_row_length) ; + + /* === Kill the pivotal column ====================================== */ + + KILL_PRINCIPAL_COL (pivot_col) ; + + /* ------------------ */ + /* added for UMFPACK: */ + /* add columns to column list of front */ +#ifndef NDEBUG + DEBUG1 (("Pivot")) ; + dump_super (pivot_col, Col, n_col) ; +#endif + Col [Col [pivot_col].lastcol].nextcol = Front_cols [nfr] ; + Front_cols [nfr] = pivot_col ; + /* ------------------ */ + + /* === Clear mark =================================================== */ + + tag_mark += (max_deg + 1) ; + if (tag_mark >= max_mark) + { + DEBUG2 (("clearing tag_mark\n")) ; + tag_mark = clear_mark (n_row, Row) ; + } + +#ifndef NDEBUG + DEBUG3 (("check3\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Finalize the new pivot row, and column scores ================ */ + + DEBUG3 (("** Finalize scores phase. **\n")) ; + DEBUG3 (("pivot_row_degree "ID"\n", pivot_row_degree)) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + /* compact the pivot row */ + new_rp = rp ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + DEBUG3 (("Col "ID" \n", col)) ; + /* skip dead columns */ + if (COL_IS_DEAD (col)) + { + DEBUG3 (("dead\n")) ; + continue ; + } + *new_rp++ = col ; + /* add new pivot row to column */ + A [Col [col].start + (Col [col].length++)] = pivot_row ; + + /* retrieve score so far and add on pivot row's degree. */ + /* (we wait until here for this in case the pivot */ + /* row's degree was reduced due to mass elimination). */ + cur_score = Col [col].shared2.score + pivot_row_degree ; + DEBUG3 ((" cur_score "ID" ", cur_score)) ; + + /* calculate the max possible score as the number of */ + /* external columns minus the 'k' value minus the */ + /* columns thickness */ + max_score = n_col - k - Col [col].shared1.thickness ; + DEBUG3 ((" max_score "ID" ", max_score)) ; + + /* make the score the external degree of the union-of-rows */ + cur_score -= Col [col].shared1.thickness ; + DEBUG3 ((" cur_score "ID" ", cur_score)) ; + + /* make sure score is less or equal than the max score */ + cur_score = MIN (cur_score, max_score) ; + ASSERT (cur_score >= 0) ; + + /* store updated score */ + Col [col].shared2.score = cur_score ; + DEBUG3 ((" "ID"\n", cur_score)) ; + + /* === Place column back in degree list ========================= */ + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (head [cur_score] >= EMPTY) ; + next_col = head [cur_score] ; + Col [col].shared4.degree_next = next_col ; + Col [col].shared3.prev = EMPTY ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = col ; + } + head [cur_score] = col ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, cur_score) ; + + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; +#endif /* NDEBUG */ + + /* ------------------ */ + /* added for UMFPACK: */ + /* frontal matrix can have more pivot cols than pivot rows for */ + /* singular matrices. */ + + /* number of candidate pivot columns */ + Front_npivcol [nfr] = pivot_col_thickness ; + + /* all rows (not just size of contrib. block) */ + Front_nrows [nfr] = pivot_row_thickness ; + + /* all cols */ + Front_ncols [nfr] = pivot_col_thickness + pivot_row_degree ; + + Front_parent [nfr] = EMPTY ; + + pivot_row_thickness -= pivot_col_thickness ; + DEBUG1 (("Front "ID" Pivot_row_thickness after pivot cols elim: "ID"\n", + nfr, pivot_row_thickness)) ; + pivot_row_thickness = MAX (0, pivot_row_thickness) ; + /* ------------------ */ + + /* === Resurrect the new pivot row ================================== */ + + if (pivot_row_degree > 0 + /* ------------------ */ + /* added for UMFPACK. Note that this part of the expression should be + * removed if this routine is used outside of UMFPACK, for a Cholesky + * factorization of (AQ)'(AQ) */ + && pivot_row_thickness > 0 + /* ------------------ */ + ) + { + /* update pivot row length to reflect any cols that were killed */ + /* during super-col detection and mass elimination */ + Row [pivot_row].start = pivot_row_start ; + Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ; + ASSERT (Row [pivot_row].length > 0) ; + Row [pivot_row].shared1.degree = pivot_row_degree ; + Row [pivot_row].shared2.mark = 0 ; + /* ------------------ */ + /* added for UMFPACK: */ + Row [pivot_row].thickness = pivot_row_thickness ; + Row [pivot_row].front = nfr ; + /* ------------------ */ + /* pivot row is no longer dead */ + } + + /* ------------------ */ + /* added for UMFPACK: */ + +#ifndef NDEBUG + DEBUG1 (("Front "ID" : "ID" "ID" "ID" ", nfr, + Front_npivcol [nfr], Front_nrows [nfr], Front_ncols [nfr])) ; + DEBUG1 ((" cols:[ ")) ; + debug_d = 0 ; + for (col = Front_cols [nfr] ; col != EMPTY ; col = Col [col].nextcol) + { + DEBUG1 ((" "ID, col)) ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (COL_IS_DEAD (col)) ; + debug_d++ ; + ASSERT (debug_d <= pivot_col_thickness) ; + } + ASSERT (debug_d == pivot_col_thickness) ; + DEBUG1 ((" ]\n ")) ; +#endif + nfr++ ; /* one more front */ + /* ------------------ */ + + } + + /* === All principal columns have now been ordered ====================== */ + + /* ------------------ */ + /* added for UMFPACK: */ + *p_nfr = nfr ; + /* ------------------ */ + + return (ngarbage) ; +} + + +/* ========================================================================== */ +/* === order_children deleted for UMFPACK =================================== */ +/* ========================================================================== */ + +/* ========================================================================== */ +/* === detect_super_cols ==================================================== */ +/* ========================================================================== */ + +/* + Detects supercolumns by finding matches between columns in the hash buckets. + Check amongst columns in the set A [row_start ... row_start + row_length-1]. + The columns under consideration are currently *not* in the degree lists, + and have already been placed in the hash buckets. + + The hash bucket for columns whose hash function is equal to h is stored + as follows: + + if head [h] is >= 0, then head [h] contains a degree list, so: + + head [h] is the first column in degree bucket h. + Col [head [h]].headhash gives the first column in hash bucket h. + + otherwise, the degree list is empty, and: + + -(head [h] + 2) is the first column in hash bucket h. + + For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous + column" pointer. Col [c].shared3.hash is used instead as the hash number + for that column. The value of Col [c].shared4.hash_next is the next column + in the same hash bucket. + + Assuming no, or "few" hash collisions, the time taken by this routine is + linear in the sum of the sizes (lengths) of each column whose score has + just been computed in the approximate degree computation. + Not user-callable. +*/ + +PRIVATE void detect_super_cols +( + /* === Parameters ======================================================= */ + +#ifndef NDEBUG + /* these two parameters are only needed when debugging is enabled: */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ +#endif /* NDEBUG */ + + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A */ + Int head [], /* head of degree lists and hash buckets */ + Int row_start, /* pointer to set of columns to check */ + Int row_length /* number of columns to check */ +) +{ + /* === Local variables ================================================== */ + + Int hash ; /* hash value for a column */ + Int *rp ; /* pointer to a row */ + Int c ; /* a column index */ + Int super_c ; /* column index of the column to absorb into */ + Int *cp1 ; /* column pointer for column super_c */ + Int *cp2 ; /* column pointer for column c */ + Int length ; /* length of column super_c */ + Int prev_c ; /* column preceding c in hash bucket */ + Int i ; /* loop counter */ + Int *rp_end ; /* pointer to the end of the row */ + Int col ; /* a column index in the row to check */ + Int head_column ; /* first column in hash bucket or degree list */ + Int first_col ; /* first column in hash bucket */ + + /* === Consider each column in the row ================================== */ + + rp = &A [row_start] ; + rp_end = rp + row_length ; + while (rp < rp_end) + { + col = *rp++ ; + if (COL_IS_DEAD (col)) + { + continue ; + } + + /* get hash number for this column */ + hash = Col [col].shared3.hash ; + ASSERT (hash <= n_col) ; + + /* === Get the first column in this hash bucket ===================== */ + + head_column = head [hash] ; + if (head_column > EMPTY) + { + first_col = Col [head_column].shared3.headhash ; + } + else + { + first_col = - (head_column + 2) ; + } + + /* === Consider each column in the hash bucket ====================== */ + + for (super_c = first_col ; super_c != EMPTY ; + super_c = Col [super_c].shared4.hash_next) + { + ASSERT (COL_IS_ALIVE (super_c)) ; + ASSERT (Col [super_c].shared3.hash == hash) ; + length = Col [super_c].length ; + + /* prev_c is the column preceding column c in the hash bucket */ + prev_c = super_c ; + + /* === Compare super_c with all columns after it ================ */ + + for (c = Col [super_c].shared4.hash_next ; + c != EMPTY ; c = Col [c].shared4.hash_next) + { + ASSERT (c != super_c) ; + ASSERT (COL_IS_ALIVE (c)) ; + ASSERT (Col [c].shared3.hash == hash) ; + + /* not identical if lengths or scores are different */ + if (Col [c].length != length || + Col [c].shared2.score != Col [super_c].shared2.score) + { + prev_c = c ; + continue ; + } + + /* compare the two columns */ + cp1 = &A [Col [super_c].start] ; + cp2 = &A [Col [c].start] ; + + for (i = 0 ; i < length ; i++) + { + /* the columns are "clean" (no dead rows) */ + ASSERT (ROW_IS_ALIVE (*cp1)) ; + ASSERT (ROW_IS_ALIVE (*cp2)) ; + /* row indices will same order for both supercols, */ + /* no gather scatter nessasary */ + if (*cp1++ != *cp2++) + { + break ; + } + } + + /* the two columns are different if the for-loop "broke" */ + if (i != length) + { + prev_c = c ; + continue ; + } + + /* === Got it! two columns are identical =================== */ + + ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ; + + Col [super_c].shared1.thickness += Col [c].shared1.thickness ; + Col [c].shared1.parent = super_c ; + KILL_NON_PRINCIPAL_COL (c) ; + + Col [c].shared2.order = EMPTY ; + /* remove c from hash bucket */ + Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ; + + /* ------------------ */ + /* added for UMFPACK: */ + /* add c to end of list of super_c */ + ASSERT (Col [super_c].lastcol >= 0) ; + ASSERT (Col [super_c].lastcol < n_col) ; + Col [Col [super_c].lastcol].nextcol = c ; + Col [super_c].lastcol = Col [c].lastcol ; +#ifndef NDEBUG + /* dump the supercolumn */ + DEBUG1 (("Super")) ; + dump_super (super_c, Col, n_col) ; +#endif + /* ------------------ */ + + } + } + + /* === Empty this hash bucket ======================================= */ + + if (head_column > EMPTY) + { + /* corresponding degree list "hash" is not empty */ + Col [head_column].shared3.headhash = EMPTY ; + } + else + { + /* corresponding degree list "hash" is empty */ + head [hash] = EMPTY ; + } + } +} + + +/* ========================================================================== */ +/* === garbage_collection =================================================== */ +/* ========================================================================== */ + +/* + Defragments and compacts columns and rows in the workspace A. Used when + all avaliable memory has been used while performing row merging. Returns + the index of the first free position in A, after garbage collection. The + time taken by this routine is linear is the size of the array A, which is + itself linear in the number of nonzeros in the input matrix. + Not user-callable. +*/ + +PRIVATE Int garbage_collection /* returns the new value of pfree */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows */ + Int n_col, /* number of columns */ + Colamd_Row Row [], /* row info */ + Colamd_Col Col [], /* column info */ + Int A [], /* A [0 ... Alen-1] holds the matrix */ + Int *pfree /* &A [0] ... pfree is in use */ +) +{ + /* === Local variables ================================================== */ + + Int *psrc ; /* source pointer */ + Int *pdest ; /* destination pointer */ + Int j ; /* counter */ + Int r ; /* a row index */ + Int c ; /* a column index */ + Int length ; /* length of a row or column */ + +#ifndef NDEBUG + Int debug_rows ; + DEBUG2 (("Defrag..\n")) ; + for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; + debug_rows = 0 ; +#endif /* NDEBUG */ + + /* === Defragment the columns =========================================== */ + + pdest = &A[0] ; + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + psrc = &A [Col [c].start] ; + + /* move and compact the column */ + ASSERT (pdest <= psrc) ; + Col [c].start = (Int) (pdest - &A [0]) ; + length = Col [c].length ; + for (j = 0 ; j < length ; j++) + { + r = *psrc++ ; + if (ROW_IS_ALIVE (r)) + { + *pdest++ = r ; + } + } + Col [c].length = (Int) (pdest - &A [Col [c].start]) ; + } + } + + /* === Prepare to defragment the rows =================================== */ + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + if (Row [r].length == 0) + { + /* :: defrag row kill :: */ + /* This row is of zero length. cannot compact it, so kill it. + * NOTE: in the current version, there are no zero-length live + * rows when garbage_collection is called. So this code will + * never trigger. However, if the code is modified, or if + * garbage_collection is called at a different place, then rows + * can be of zero length. So this test is kept, just in case. + */ + DEBUGm4 (("Defrag row kill\n")) ; + KILL_ROW (r) ; + } + else + { + /* save first column index in Row [r].shared2.first_column */ + psrc = &A [Row [r].start] ; + Row [r].shared2.first_column = *psrc ; + ASSERT (ROW_IS_ALIVE (r)) ; + /* flag the start of the row with the one's complement of row */ + *psrc = ONES_COMPLEMENT (r) ; +#ifndef NDEBUG + debug_rows++ ; +#endif /* NDEBUG */ + } + } + } + + /* === Defragment the rows ============================================== */ + + psrc = pdest ; + while (psrc < pfree) + { + /* find a negative number ... the start of a row */ + if (*psrc++ < 0) + { + psrc-- ; + /* get the row index */ + r = ONES_COMPLEMENT (*psrc) ; + ASSERT (r >= 0 && r < n_row) ; + /* restore first column index */ + *psrc = Row [r].shared2.first_column ; + ASSERT (ROW_IS_ALIVE (r)) ; + + /* move and compact the row */ + ASSERT (pdest <= psrc) ; + Row [r].start = (Int) (pdest - &A [0]) ; + length = Row [r].length ; + for (j = 0 ; j < length ; j++) + { + c = *psrc++ ; + if (COL_IS_ALIVE (c)) + { + *pdest++ = c ; + } + } + Row [r].length = (Int) (pdest - &A [Row [r].start]) ; + +#ifndef NDEBUG + debug_rows-- ; +#endif /* NDEBUG */ + + } + } + /* ensure we found all the rows */ + ASSERT (debug_rows == 0) ; + + /* === Return the new value of pfree ==================================== */ + + return ((Int) (pdest - &A [0])) ; +} + + +/* ========================================================================== */ +/* === clear_mark =========================================================== */ +/* ========================================================================== */ + +/* + Clears the Row [].shared2.mark array, and returns the new tag_mark. + Return value is the new tag_mark. Not user-callable. +*/ + +PRIVATE Int clear_mark /* return the new value for tag_mark */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows in A */ + Colamd_Row Row [] /* Row [0 ... n-1].shared2.mark is set to zero */ +) +{ + /* === Local variables ================================================== */ + + Int r ; + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + Row [r].shared2.mark = 0 ; + } + } + + /* ------------------ */ + return (1) ; + /* ------------------ */ + +} + + +/* ========================================================================== */ +/* === print_report removed for UMFPACK ===================================== */ +/* ========================================================================== */ + + + +/* ========================================================================== */ +/* === colamd debugging routines ============================================ */ +/* ========================================================================== */ + +/* When debugging is disabled, the remainder of this file is ignored. */ + +#ifndef NDEBUG + + +/* ========================================================================== */ +/* === debug_structures ===================================================== */ +/* ========================================================================== */ + +/* + At this point, all empty rows and columns are dead. All live columns + are "clean" (containing no dead rows) and simplicial (no supercolumns + yet). Rows may contain dead columns, but all live rows contain at + least one live column. +*/ + +PRIVATE void debug_structures +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) +{ + /* === Local variables ================================================== */ + + Int i ; + Int c ; + Int *cp ; + Int *cp_end ; + Int len ; + Int score ; + Int r ; + Int *rp ; + Int *rp_end ; + Int deg ; + + /* === Check A, Row, and Col ============================================ */ + + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + len = Col [c].length ; + score = Col [c].shared2.score ; + DEBUG4 (("initial live col "ID" "ID" "ID"\n", c, len, score)) ; + ASSERT (len > 0) ; + ASSERT (score >= 0) ; + ASSERT (Col [c].shared1.thickness == 1) ; + cp = &A [Col [c].start] ; + cp_end = cp + len ; + while (cp < cp_end) + { + r = *cp++ ; + ASSERT (ROW_IS_ALIVE (r)) ; + } + } + else + { + i = Col [c].shared2.order ; + ASSERT (i >= n_col2 && i < n_col) ; + } + } + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + i = 0 ; + len = Row [r].length ; + deg = Row [r].shared1.degree ; + ASSERT (len > 0) ; + ASSERT (deg > 0) ; + rp = &A [Row [r].start] ; + rp_end = rp + len ; + while (rp < rp_end) + { + c = *rp++ ; + if (COL_IS_ALIVE (c)) + { + i++ ; + } + } + ASSERT (i > 0) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_deg_lists ====================================================== */ +/* ========================================================================== */ + +/* + Prints the contents of the degree lists. Counts the number of columns + in the degree list and compares it to the total it should have. Also + checks the row degrees. +*/ + +PRIVATE void debug_deg_lists +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) +{ + /* === Local variables ================================================== */ + + Int deg ; + Int col ; + Int have ; + Int row ; + + /* === Check the degree lists =========================================== */ + + if (n_col > 10000 && UMF_debug <= 0) + { + return ; + } + have = 0 ; + DEBUG4 (("Degree lists: "ID"\n", min_score)) ; + for (deg = 0 ; deg <= n_col ; deg++) + { + col = head [deg] ; + if (col == EMPTY) + { + continue ; + } + DEBUG4 ((ID":", deg)) ; + while (col != EMPTY) + { + DEBUG4 ((" "ID, col)) ; + have += Col [col].shared1.thickness ; + ASSERT (COL_IS_ALIVE (col)) ; + col = Col [col].shared4.degree_next ; + } + DEBUG4 (("\n")) ; + } + DEBUG4 (("should "ID" have "ID"\n", should, have)) ; + ASSERT (should == have) ; + + /* === Check the row degrees ============================================ */ + + if (n_row > 10000 && UMF_debug <= 0) + { + return ; + } + for (row = 0 ; row < n_row ; row++) + { + if (ROW_IS_ALIVE (row)) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_mark =========================================================== */ +/* ========================================================================== */ + +/* + Ensures that the tag_mark is less that the maximum and also ensures that + each entry in the mark array is less than the tag mark. +*/ + +PRIVATE void debug_mark +( + /* === Parameters ======================================================= */ + + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) +{ + /* === Local variables ================================================== */ + + Int r ; + + /* === Check the Row marks ============================================== */ + + ASSERT (tag_mark > 0 && tag_mark <= max_mark) ; + if (n_row > 10000 && UMF_debug <= 0) + { + return ; + } + for (r = 0 ; r < n_row ; r++) + { + ASSERT (Row [r].shared2.mark < tag_mark) ; + } +} + + +/* ========================================================================== */ +/* === debug_matrix ========================================================= */ +/* ========================================================================== */ + +/* + Prints out the contents of the columns and the rows. +*/ + +PRIVATE void debug_matrix +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) +{ + /* === Local variables ================================================== */ + + Int r ; + Int c ; + Int *rp ; + Int *rp_end ; + Int *cp ; + Int *cp_end ; + + /* === Dump the rows and columns of the matrix ========================== */ + + if (UMF_debug < 3) + { + return ; + } + DEBUG3 (("DUMP MATRIX:\n")) ; + for (r = 0 ; r < n_row ; r++) + { + DEBUG3 (("Row "ID" alive? %d\n", r, ROW_IS_ALIVE (r))) ; + if (ROW_IS_DEAD (r)) + { + continue ; + } + + /* ------------------ */ + /* changed for UMFPACK: */ + DEBUG3 (("start "ID" length "ID" degree "ID" thickness "ID"\n", + Row [r].start, Row [r].length, Row [r].shared1.degree, + Row [r].thickness)) ; + /* ------------------ */ + + rp = &A [Row [r].start] ; + rp_end = rp + Row [r].length ; + while (rp < rp_end) + { + c = *rp++ ; + DEBUG4 ((" %d col "ID"\n", COL_IS_ALIVE (c), c)) ; + } + } + + for (c = 0 ; c < n_col ; c++) + { + DEBUG3 (("Col "ID" alive? %d\n", c, COL_IS_ALIVE (c))) ; + if (COL_IS_DEAD (c)) + { + continue ; + } + /* ------------------ */ + /* changed for UMFPACK: */ + DEBUG3 (("start "ID" length "ID" shared1[thickness,parent] "ID + " shared2 [order,score] "ID"\n", Col [c].start, Col [c].length, + Col [c].shared1.thickness, Col [c].shared2.score)); + /* ------------------ */ + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + r = *cp++ ; + DEBUG4 ((" %d row "ID"\n", ROW_IS_ALIVE (r), r)) ; + } + + /* ------------------ */ + /* added for UMFPACK: */ + DEBUG1 (("Col")) ; + dump_super (c, Col, n_col) ; + /* ------------------ */ + + } +} + +/* ------------------ */ +/* dump_super added for UMFPACK: */ +PRIVATE void dump_super +( + Int super_c, + Colamd_Col Col [], + Int n_col +) +{ + Int col, ncols ; + + DEBUG1 ((" =[ ")) ; + ncols = 0 ; + for (col = super_c ; col != EMPTY ; col = Col [col].nextcol) + { + DEBUG1 ((" "ID, col)) ; + ASSERT (col >= 0 && col < n_col) ; + if (col != super_c) + { + ASSERT (COL_IS_DEAD (col)) ; + } + if (Col [col].nextcol == EMPTY) + { + ASSERT (col == Col [super_c].lastcol) ; + } + ncols++ ; + ASSERT (ncols <= Col [super_c].shared1.thickness) ; + } + ASSERT (ncols == Col [super_c].shared1.thickness) ; + DEBUG1 (("]\n")) ; +} +/* ------------------ */ + + +#endif /* NDEBUG */ diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.h b/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_colamd.h @@ -0,0 +1,255 @@ +/* ========================================================================== */ +/* === umf_colamd.h ========================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + +Authors: + + The authors of the COLAMD code itself are Stefan I. Larimore and Timothy A. + Davis, University of Florida. The algorithm was developed in collaboration + with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. + +Date: + + UMFPACK Version: see above. + COLAMD Version 2.0 was released on January 31, 2000. + +Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974, DMS-9803599, and CCR-0203270. + +UMFPACK: Copyright (c) 2003 by Timothy A. Davis. All Rights Reserved. + +See the UMFPACK README file for the License for your use of this code. + +Availability: + + Both UMFPACK and the original unmodified colamd/symamd library are + available at http://www.cise.ufl.edu/research/sparse. + +*/ + +#ifndef COLAMD_H +#define COLAMD_H + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include + +/* ========================================================================== */ +/* === Knob and statistics definitions ====================================== */ +/* ========================================================================== */ + +/* size of the knobs [ ] array. Only knobs [0..2] are currently used. */ +#define COLAMD_KNOBS 20 + +/* number of output statistics. Only stats [0..8] are currently used. */ +#define COLAMD_STATS 20 + +/* knobs [0] and stats [0]: dense row knob and output statistic. */ +#define COLAMD_DENSE_ROW 0 + +/* knobs [1] and stats [1]: dense column knob and output statistic. */ +#define COLAMD_DENSE_COL 1 + +/* knobs [2]: aggressive absorption option */ +#define COLAMD_AGGRESSIVE 2 + +/* stats [2]: memory defragmentation count output statistic */ +#define COLAMD_DEFRAG_COUNT 2 + +/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */ +#define COLAMD_STATUS 3 + +/* stats [4..6]: error info, or info on jumbled columns */ +#define COLAMD_INFO1 4 +#define COLAMD_INFO2 5 +#define COLAMD_INFO3 6 + +/* ------------------ */ +/* added for UMFPACK: */ +/* stats [7]: number of originally empty rows */ +#define COLAMD_EMPTY_ROW 7 +/* stats [8]: number of originally empty cols */ +#define COLAMD_EMPTY_COL 8 +/* stats [9]: number of rows with entries only in dense cols */ +#define COLAMD_NEWLY_EMPTY_ROW 9 +/* stats [10]: number of cols with entries only in dense rows */ +#define COLAMD_NEWLY_EMPTY_COL 10 +/* ------------------ */ + +/* error codes returned in stats [3]: */ +#define COLAMD_OK (0) +#define COLAMD_ERROR_jumbled_matrix (-11) +#define COLAMD_ERROR_A_not_present (-1) +#define COLAMD_ERROR_p_not_present (-2) +#define COLAMD_ERROR_nrow_negative (-3) +#define COLAMD_ERROR_ncol_negative (-4) +#define COLAMD_ERROR_nnz_negative (-5) +#define COLAMD_ERROR_p0_nonzero (-6) +#define COLAMD_ERROR_A_too_small (-7) +#define COLAMD_ERROR_col_length_negative (-8) +#define COLAMD_ERROR_row_index_out_of_bounds (-9) +#define COLAMD_ERROR_out_of_memory (-10) +#define COLAMD_ERROR_internal_error (-999) + +/* ========================================================================== */ +/* === Row and Column structures ============================================ */ +/* ========================================================================== */ + +/* User code that makes use of the colamd/symamd routines need not directly */ +/* reference these structures. They are used only for the COLAMD_RECOMMENDED */ +/* macro. */ + +typedef struct Colamd_Col_struct +{ + Int start ; /* index for A of first row in this column, or DEAD */ + /* if column is dead */ + Int length ; /* number of rows in this column */ + union + { + Int thickness ; /* number of original columns represented by this */ + /* col, if the column is alive */ + Int parent ; /* parent in parent tree super-column structure, if */ + /* the column is dead */ + } shared1 ; + union + { + Int score ; /* the score used to maintain heap, if col is alive */ + Int order ; /* pivot ordering of this column, if col is dead */ + } shared2 ; + union + { + Int headhash ; /* head of a hash bucket, if col is at the head of */ + /* a degree list */ + Int hash ; /* hash value, if col is not in a degree list */ + Int prev ; /* previous column in degree list, if col is in a */ + /* degree list (but not at the head of a degree list) */ + } shared3 ; + union + { + Int degree_next ; /* next column, if col is in a degree list */ + Int hash_next ; /* next column, if col is in a hash list */ + } shared4 ; + + /* ------------------ */ + /* added for UMFPACK: */ + Int nextcol ; /* next column in this supercolumn */ + Int lastcol ; /* last column in this supercolumn */ + /* ------------------ */ + +} Colamd_Col ; + +typedef struct Colamd_Row_struct +{ + Int start ; /* index for A of first col in this row */ + Int length ; /* number of principal columns in this row */ + union + { + Int degree ; /* number of principal & non-principal columns in row */ + Int p ; /* used as a row pointer in init_rows_cols () */ + } shared1 ; + union + { + Int mark ; /* for computing set differences and marking dead rows*/ + Int first_column ;/* first column in row (used in garbage collection) */ + } shared2 ; + + /* ------------------ */ + /* added for UMFPACK: */ + Int thickness ; /* number of original rows represented by this row */ + /* that are not yet pivotal */ + Int front ; /* -1 if an original row */ + /* k if this row represents the kth frontal matrix */ + /* where k goes from 0 to at most n_col-1 */ + /* ------------------ */ + +} Colamd_Row ; + + + +/* ========================================================================== */ +/* === Colamd recommended memory size ======================================= */ +/* ========================================================================== */ + +/* + The recommended length Alen of the array A passed to colamd is given by + the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any + argument is negative. 2*nnz space is required for the row and column + indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is + required for the Col and Row arrays, respectively, which are internal to + colamd. An additional n_col space is the minimal amount of "elbow room", + and nnz/5 more space is recommended for run time efficiency. + + This macro is not needed when using symamd. +*/ + +/* about 8*(n_col+1) integers: */ +#define UMF_COLAMD_C(n_col) ((n_col + 1) * sizeof (Colamd_Col) / sizeof (Int)) + +/* about 6*(n_row+1) integers: */ +#define UMF_COLAMD_R(n_row) ((n_row + 1) * sizeof (Colamd_Row) / sizeof (Int)) + +/* UMFPACK: make sure Alen is >= 5*n_col + size of Col and Row structures. + * Alen is typically about 2.2*nz + 9*n_col + 6*n_row, or 2.2nz+15n for + * square matrices. */ +#define UMF_COLAMD_RECOMMENDED(nnz, n_row, n_col) \ +( \ +((nnz) < 0 || (n_row) < 0 || (n_col) < 0) \ +? \ + (-1) \ +: \ + (MAX (2 * (nnz), 4 * (n_col)) + \ + (Int) UMF_COLAMD_C (n_col) + \ + (Int) UMF_COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \ +) + +/* ========================================================================== */ +/* === Prototypes of user-callable routines ================================= */ +/* ========================================================================== */ + +/* colamd_recommended removed for UMFPACK */ + +void UMF_colamd_set_defaults /* sets default parameters */ +( /* knobs argument is modified on output */ + double knobs [COLAMD_KNOBS] /* parameter settings for colamd */ +) ; + +Int UMF_colamd /* returns (1) if successful, (0) otherwise*/ +( /* A and p arguments are modified on output */ + Int n_row, /* number of rows in A */ + Int n_col, /* number of columns in A */ + Int Alen, /* size of the array A */ + Int A [], /* row indices of A, of size Alen */ + Int p [], /* column pointers of A, of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameter settings for colamd */ + Int stats [COLAMD_STATS] /* colamd output statistics and error codes */ + /* ------------------ */ + /* added for UMFPACK: */ + , Int Front_npivcol [ ] + , Int Front_nrows [ ] + , Int Front_ncols [ ] + , Int Front_parent [ ] + , Int Front_cols [ ] + , Int *p_nfr + , Int InFront [ ] + /* ------------------ */ +) ; + +/* symamd deleted for UMFPACK */ + +/* colamd_report deleted for UMFPACK */ + +/* symamd_report deleted for UMFPACK */ + +#endif /* COLAMD_H */ diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_config.h b/liboctave/UMFPACK/UMFPACK/Source/umf_config.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_config.h @@ -0,0 +1,919 @@ +/* ========================================================================== */ +/* === umf_config.h ========================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + This file controls the compile-time configuration of UMFPACK. Modify the + Makefile, the architecture-dependent Make.* file, and this file if + necessary, to control these options. The following flags may be given + as options to your C compiler (as in "cc -DNBLAS", for example). These + flags are normally placed in your CONFIG string, defined in your Make.*. + + All of these options, except for the timer, are for accessing the BLAS. + + -DNBLAS + + BLAS mode. If -DNBLAS is set, then no BLAS will be used. Vanilla + C code will be used instead. This is portable, and easier to + install, but you won't get the best performance. + + If -DNBLAS is not set, then externally-available BLAS routines + (dgemm, dger, and dgemv or the equivalent C-BLAS routines) will be + used. This will give you the best performance, but perhaps at the + expense of portability. + + The default is to use the BLAS, for both the C-callable libumfpack.a + library and the MATLAB mexFunction. If you have trouble installing + UMFPACK, set -DNBLAS (but then UMFPACK will be slow). + + -DCBLAS + + If -DCBLAS is set, then the C-BLAS interface to the BLAS is + used. If your vendor-supplied BLAS library does not have a C-BLAS + interface, you can obtain the ATLAS BLAS, available at + http://www.netlib.org/atlas. + + This flag is ignored if -DNBLAS is set. + + -DLP64 + + This should be defined if you are compiling in the LP64 model + (32 bit int's, 64 bit long's, and 64 bit pointers). In Solaris, + this is obtained with the flags -xtarget=ultra -xarch=v9 for + the cc compiler (for example). + + -DLONGBLAS + + If not defined, then the BLAS are not called in the long integer + version of UMFPACK (the umfpack_*l_* routines). The most common + definitions of the BLAS, unfortunately, use int arguments, and + are thus not suitable for use in the LP64 model. Only the Sun + Performance Library, as far as I can tell, has a version of the + BLAS that allows long integer (64-bit) input arguments. This + flag is set automatically in Sun Solaris if you are using the + Sun Performance BLAS. You can set it yourself, too, if your BLAS + routines can take long integer input arguments. + + -DNSUNPERF + + Applies only to Sun Solaris. If -DNSUNPERF is set, then the Sun + Performance Library BLAS will not be used. + + The Sun Performance Library BLAS is used by default when compiling + the C-callable libumfpack.a library on Sun Solaris. + + This flag is ignored if -DNBLAS is set. + + -DNSCSL + + Applies only to SGI IRIX. If -DSCSL is set, then the SGI SCSL + Scientific Library BLAS will not be used. + + The SGI SCSL Scientific Library BLAS is used by default when + compiling the C-callable libumfpack.a library on SGI IRIX. + + This flag is ignored if -DNBLAS is set. + + -DNPOSIX + + If -DNPOSIX is set, then your Unix operating system is not POSIX- + compliant, and the POSIX routines sysconf ( ) and times ( ) + routines are not used. These routines provide CPU time and + wallclock time information. If -DNPOSIX is set, then the ANSI + C clock ( ) routine is used. If -DNPOSIX is not set, then + sysconf ( ) and times ( ) are used in umfpack_tic and umfpack_toc. + See umfpack_tictoc.c for more information. + The default is to use the POSIX routines, except for Windows, + which is not POSIX-compliant. + + -DGETRUSAGE + + If -DGETRUSAGE is set, then your system's getrusage ( ) routine + will be used for getting the process CPU time. Otherwise the ANSI + C clock ( ) routine will be used. The default is to use getrusage + ( ) on Unix systems, and to use clock on all other architectures. + + -DNO_TIMER + + If -DNO_TIMER is set, then no timing routines are used at all. + + -DNUTIL + + If -DNUTIL is set, then the internal MATLAB utMalloc, utFree, and + utRealloc routines are not used in the UMFPACK mexFunction. The + regular mxMalloc, mxFree, and mxRealloc routines are used instead. + These routines are not documented, but are available for use. For + Windows, -DNUTIL is defined below, because access to the ut* + routines is not available by default. + + -DNRECIPROCAL + + This option controls a tradeoff between speed and accuracy. Using + -DNRECIPROCAL can lead to more accurate results, but with perhaps + some cost in performance, particularly if floating-point division + is much more costly than floating-point multiplication. + + This option determines the method used to scale the pivot column. + If set, or if the absolute value of the pivot is < 1e-12 (or is a + NaN), then the pivot column is divided by the pivot value. + Otherwise, the reciprocal of the pivot value is computed, and the + pivot column is multiplied by (1/pivot). Multiplying by the + reciprocal can be slightly less accurate than dividing by the + pivot, but it is often faster. See umf_scale.c. + + This has a small effect on the performance of UMFPACK, at least on + a Pentium 4M. It may have a larger effect on other architectures + where floating-point division is much more costly than floating- + point multiplication. The RS 6000 is one such example. + + By default, the method chosen is to multiply by the reciprocal + (sacrificing accuracy for speed), except when compiling UMFPACK + as a built-in routine in MATLAB, or when gcc is being used. + + When MATHWORKS is defined, -DNRECIPROCAL is forced on, and the pivot + column is divided by the pivot value. The only way of using the + other method in this case is to edit this file. + + If -DNRECIPROCAL is enabled, then the row scaling factors are always + applied by dividing each row by the scale factor, rather than + multiplying by the reciprocal. If -DNRECIPROCAL is not enabled + (the default case), then the scale factors are normally applied by + multiplying by the reciprocal. If, however, the smallest scale + factor is tiny, then the scale factors are applied via division. + + -DNO_DIVIDE_BY_ZERO + + If the pivot is zero, and this flag is set, then no divide-by-zero + occurs. + + You should normally not set these flags yourself: + + -DBLAS_BY_VALUE if scalars are passed by value, not reference + -DBLAS_NO_UNDERSCORE if no underscore should be appended + -DBLAS_CHAR_ARG if BLAS options are single char's, not strings + + The BLAS options are normally set automatically. If your + architecture cannot be determined (see UMFPACK_ARCHITECTURE, below) + then you may need to set these flags yourself. + + The following options are controlled by amd_internal.h: + + -DMATLAB_MEX_FILE + + This flag is turned on when compiling the umfpack mexFunction for + use in MATLAB. When compiling the MATLAB mexFunction, the MATLAB + BLAS are used (unless -DNBLAS is set). The -DCBLAS, -DNSCSL, and + -DNSUNPERF flags are all ignored. The -DNRECIPROCAL flag is + forced on. Otherwise, [L,U,P,Q,R] = umfpack (A) would return + either L*U = P*(R\A)*Q or L*U = P*R*A*Q. Rather than returning a + flag stating how the scale factors R are to be applied, the umfpack + mexFunction always takes the more accurate route and returns + L*U = P*(R\A)*Q. + + -DMATHWORKS + + This flag is turned on when compiling umfpack as a built-in routine + in MATLAB. The MATLAB BLAS are used for all architectures (-DNBLAS, + -DCBLAS, -DNSCSL, and -DNSUNPERF flags are all ignored). Internal + routines utMalloc, utFree, utRealloc, utPrintf, utDivideComplex, + and utFdlibm_hypot are used, and the "util.h" file is included. + This avoids the problem discussed in the User Guide regarding memory + allocation in MATLAB. utMalloc returns NULL on failure, instead of + terminating the mexFunction (which is what mxMalloc does). However, + the ut* routines are not documented by The MathWorks, Inc., so I + cannot guarantee that you will always be able to use them. + The -DNRECIPROCAL flag is turned on. + + -DNDEBUG + + Debugging mode (if NDEBUG is not defined). The default, of course, + is no debugging. Turning on debugging takes some work (see below). + If you do not edit this file, then debugging is turned off anyway, + regardless of whether or not -DNDEBUG is specified in your compiler + options. +*/ + +/* ========================================================================== */ +/* === AMD configuration ==================================================== */ +/* ========================================================================== */ + +/* NDEBUG, PRINTF defined in amd_internal.h */ + +/* ========================================================================== */ +/* === reciprocal option ==================================================== */ +/* ========================================================================== */ + +/* Force the definition NRECIPROCAL when MATHWORKS or MATLAB_MEX_FILE + * are defined. Do not multiply by the reciprocal in those cases. */ + +#ifndef NRECIPROCAL +#if defined (MATHWORKS) || defined (MATLAB_MEX_FILE) +#define NRECIPROCAL +#endif +#endif + +/* ========================================================================== */ +/* === Microsoft Windows configuration ====================================== */ +/* ========================================================================== */ + +#ifdef UMF_WINDOWS +/* Windows can't access the ut* routines, and it isn't Unix. */ +#define NUTIL +#define NPOSIX +#endif + +/* ========================================================================== */ +/* === 0-based or 1-based printing ========================================== */ +/* ========================================================================== */ + +#if defined (MATLAB_MEX_FILE) && defined (NDEBUG) +/* In MATLAB, matrices are 1-based to the user, but 0-based internally. */ +/* One is added to all row and column indices when printing matrices */ +/* for the MATLAB user. The +1 shift is turned off when debugging. */ +#define INDEX(i) ((i)+1) +#else +/* In ANSI C, matrices are 0-based and indices are reported as such. */ +/* This mode is also used for debug mode, and if MATHWORKS is defined rather */ +/* than MATLAB_MEX_FILE. */ +#define INDEX(i) (i) +#endif + +/* ========================================================================== */ +/* === Timer ================================================================ */ +/* ========================================================================== */ + +/* + If you have the getrusage routine (all Unix systems I've test do), then use + that. Otherwise, use the ANSI C clock function. Note that on many + systems, the ANSI clock function wraps around after only 2147 seconds, or + about 36 minutes. BE CAREFUL: if you compare the run time of UMFPACK with + other sparse matrix packages, be sure to use the same timer. See + umfpack_tictoc.c for the timer used internally by UMFPACK. See also + umfpack_timer.c for the timer used in an earlier version of UMFPACK. + That timer is still available as a user-callable routine, but it is no + longer used internally by UMFPACK. +*/ + +/* Sun Solaris, SGI Irix, Linux, Compaq Alpha, and IBM RS 6000 all have */ +/* getrusage. It's in BSD unix, so perhaps all unix systems have it. */ +#if defined (UMF_SOL2) || defined (UMF_SGI) || defined (UMF_LINUX) \ +|| defined (UMF_ALPHA) || defined (UMF_AIX) +#define GETRUSAGE +#endif + + +/* ========================================================================== */ +/* === BLAS ================================================================= */ +/* ========================================================================== */ + +/* + The adventure begins. Figure out how to call the BLAS ... + + This works, but it is incredibly ugly. The C-BLAS was supposed to solve + this problem, and make it easier to interface a C program to the BLAS. + Unfortunately, the C-BLAS does not have a "long" integer (64 bit) version. + Various vendors have done their own 64-bit BLAS. Sun has dgemm_64 routines + with "long" integers, SGI has a 64-bit dgemm in their scsl_blas_i8 library + with "long long" integers, and so on. + + Different vendors also have different ways of defining a complex number, + some using struct's. That's a bad idea. See umf_version.h for the better + way to do it (the method that was also chosen for the complex C-BLAS, + which is compatible and guaranteed to be portable with ANSI C). + + To make matters worse, SGI's SCSL BLAS has a C-BLAS interface which + differs from the ATLAS C-BLAS interface (see immediately below); + although a more recent version of SGI's C-BLAS interface is correct + if SCSL_VOID_ARGS is defined. +*/ + + +/* -------------------------------------------------------------------------- */ +/* Determine which BLAS to use. */ +/* -------------------------------------------------------------------------- */ + +#if defined (MATHWORKS) +#define USE_MATLAB_BLAS + +#elif defined (NBLAS) +#define USE_NO_BLAS + +#elif defined (MATLAB_MEX_FILE) +#define USE_MATLAB_BLAS + +#elif defined (CBLAS) +#define USE_C_BLAS + +#elif defined (UMF_SOL2) && !defined (NSUNPERF) +#define USE_SUNPERF_BLAS + +#elif defined (UMF_SGI) && !defined (NSCSL) +#define USE_SCSL_BLAS + +#else +#define USE_FORTRAN_BLAS +#endif + +/* -------------------------------------------------------------------------- */ +/* int vs. long integer arguments */ +/* -------------------------------------------------------------------------- */ + +/* + Determine if the BLAS exists for the long integer version. It exists if + LONGBLAS is defined in the Makefile, or if using the BLAS from the + Sun Performance Library, or SGI's SCSL Scientific Library. +*/ + +#if defined (USE_SUNPERF_BLAS) || defined (USE_SCSL_BLAS) +#ifndef LONGBLAS +#define LONGBLAS +#endif +#endif + +/* do not use the BLAS if Int's are long and LONGBLAS is not defined */ +#if defined (LONG_INTEGER) && !defined (LONGBLAS) && !defined (USE_NO_BLAS) +#define USE_NO_BLAS +#endif + + +/* -------------------------------------------------------------------------- */ +/* Use (void *) arguments for the SGI */ +/* -------------------------------------------------------------------------- */ + +#if defined (UMF_SGI) +/* + Use (void *) pointers for complex types in SCSL. + The ATLAS C-BLAS, and the SGI C-BLAS differ. The former uses (void *) + arguments, the latter uses SCSL_ZOMPLEX_T, which are either scsl_zomplex + or (void *). Using (void *) is simpler, and is selected by defining + SCSL_VOID_ARGS, below. The cc compiler doesn't complain, but gcc is + more picky, and generates a warning without this next statement. + With gcc and the 07/09/98 version of SGI's cblas.h, spurious warnings + about complex BLAS arguments will be reported anyway. This is because this + older version of SGI's cblas.h does not make use of the SCSL_VOID_ARGS + parameter, which is present in the 12/6/01 version of SGI's cblas.h. You + can safely ignore these warnings. +*/ +#define SCSL_VOID_ARGS +#endif + + +/* -------------------------------------------------------------------------- */ +/* The BLAS exists, construct appropriate macros */ +/* -------------------------------------------------------------------------- */ + +#if !defined (USE_NO_BLAS) /* { */ + +/* + If the compile-time flag -DNBLAS is defined, then the BLAS are not used, + portable vanilla C code is used instead, and the remainder of this file + is ignored. + + Using the BLAS is much faster, but how C calls the Fortran BLAS is + machine-dependent and thus can cause portability problems. Thus, use + -DNBLAS to ensure portability (at the expense of speed). + + Preferences: + + *** The best interface to use, regardless of the option you select + below, is the standard C-BLAS interface. Not all BLAS libraries + use this interface. The only problem with this interface is that + it does not extend to the LP64 model. The C-BLAS does not provide + for a 64-bit integer. In addition, SGI's older cblas.h can cause + spurious warnings when using the C-BLAS interface. + + 1) often the most preferred (but see option (3)): use the + optimized vendor-supplied library (such as the Sun Performance + Library, or IBM's ESSL). This is often the fastest, but might not + be portable and might not always be available. When compiling a + MATLAB mexFunction it might be difficult get the mex compiler + script to recognize the vendor- supplied BLAS. Note that the + freely-available BLAS (option 3) can be faster than the vendor- + specific BLAS. You are encourage to try both option (1) and (3). + + 2) When compiling the UMFPACK mexFunction to use UMFPACK in MATLAB, use + the BLAS provided by The Mathworks, Inc. This assumes you are using + MATLAB V6 or higher, since the BLAS are not incorporated in V5 or + earlier versions. On my Sun workstation, the MATLAB BLAS gave + slightly worse performance than the Sun Perf. BLAS. The advantage + of using the MATLAB BLAS is that it's available on any computer that + has MATLAB V6 or higher. I have not tried using MATLAB BLAS outside + of a mexFunction in a stand-alone C code, but MATLAB (V6) allows for + this. This is well worth trying if you have MATLAB and don't want + to bother installing the ATLAS BLAS (option 3a, below). The only + glitch to this is that MATLAB does not provide a portable interface + to the BLAS (an underscore is required for some but not all + architectures). For Windows and MATLAB 6.0 or 6.1, you also need + to copy the libmwlapack.dll file into your MATLAB installation + directory; see the User Guide for details. + + In the current distribution, the only BLAS that the UMFPACK + mexFunction will use is the internal MATLAB BLAS. It's possible to + use other BLAS, but handling the porting of using the mex compiler + with different BLAS libraries is not trivial. + + As of MATLAB 6.5, the BLAS used internally in MATLAB is the ATLAS + BLAS. + + 3) Use a freely-available high-performance BLAS library: + + (a) The BLAS by Kazashige Goto and Robert van de Geijn, at + http://www.cs.utexas.edu/users/flame/goto. This BLAS increased + the performance of UMFPACK by almost 50% as compared to the + ATLAS BLAS (v3.2). + + (b) The ATLAS BLAS, available at http://www.netlib.org/atlas, + by R. Clint Whaley, Antoine Petitet, and Jack Dongarra. + This has a standard C interface, and thus the interface to it is + fully portable. Its performance rivals, and sometimes exceeds, + the vendor-supplied BLAS on many computers. + + (b) The Fortran RISC BLAS by Michel Dayde', Iain Duff, Antoine + Petitet, and Abderrahim Qrichi Aniba, available via anonymous + ftp to ftp.enseeiht.fr in the pub/numerique/BLAS/RISC directory, + See M. J. Dayde' and I. S. Duff, "The RISC BLAS: A blocked + implementation of level 3 BLAS for RISC processors, ACM Trans. + Math. Software, vol. 25, no. 3., Sept. 1999. This will give + you good performance, but with the same C-to-Fortran portability + problems as option (1). + + 4) Use UMFPACK's built-in vanilla C code by setting -DNBLAS at compile + time. The key advantage is portability, which is guaranteed if you + have an ANSI C compliant compiler. You also don't need to download + any other package - UMFPACK is stand-alone. No Fortran is used + anywhere in UMFPACK. UMFPACK will be much slower than when using + options (1) through (3), however. + + 5) least preferred: use the standard Fortran implementation of the + BLAS, also available at Netlib (http://www.netlib.org/blas). This + will be no faster than option (4), and not portable because of + C-to-Fortran calling conventions. Don't bother trying option (5). + + The mechanics of how C calls the BLAS on various computers are as follows: + + * C-BLAS (from the ATLAS library, for example): + The same interface is used on all computers. + + * Defaults for calling the Fortran BLAS: + add underscore, pass scalars by reference, use string arguments. + + * The Fortran BLAS on Sun Solaris (when compiling the MATLAB mexFunction + or when using the Fortran RISC BLAS), SGI IRIX, Linux, and Compaq + Alpha: use defaults. + + * Sun Solaris (when using the C-callable Sun Performance library): + no underscore, pass scalars by value, use character arguments. + + * The Fortran BLAS (ESSL Library) on the IBM RS 6000, and HP Unix: + no underscore, pass scalars by reference, use string arguments. + + * The Fortran BLAS on Windows: + no underscore, pass scalars by reference, use string arguments. + If you compile the umfpack mexFunction using umfpack_make, and are + using the lcc compiler bundled with MATLAB, then you must first + copy the umfpack\lcc_lib\libmwlapack.lib file into the + \extern\lib\win32\lcc\ directory, where is the + directory in which MATLAB is installed. Next, type mex -setup + at the MATLAB prompt, and ask MATLAB to select the lcc compiler. + MATLAB has built-in BLAS, but it cannot be accessed by a program + compiled by lcc without first copying this file. +*/ + + + +/* -------------------------------------------------------------------------- */ +#ifdef USE_C_BLAS /* { */ +/* -------------------------------------------------------------------------- */ + + +/* -------------------------------------------------------------------------- */ +/* use the C-BLAS (any computer) */ +/* -------------------------------------------------------------------------- */ + +/* + C-BLAS is the default interface, with the following exceptions. Solaris + uses the Sun Performance BLAS for libumfpack.a (the C-callable library). + SGI IRIX uses the SCSL BLAS for libumfpack.a. All architectures use + MATLAB's internal BLAS for the mexFunction on any architecture. These + options are set in the Make.* files. The Make.generic file uses no BLAS + at all. + + If you use the ATLAS C-BLAS, then be sure to set the -I flag to + -I/path/ATLAS/include, where /path/ATLAS is the ATLAS installation + directory. See Make.solaris for an example. You do not need to do this + for the SGI, which has a /usr/include/cblas.h. +*/ + +#include "cblas.h" + +#ifdef COMPLEX +#define BLAS_GEMM_ROUTINE cblas_zgemm +#define BLAS_TRSM_ROUTINE cblas_ztrsm +#define BLAS_TRSV_ROUTINE cblas_ztrsv +#define BLAS_GEMV_ROUTINE cblas_zgemv +#define BLAS_GER_ROUTINE cblas_zgeru +#define BLAS_SCAL_ROUTINE cblas_zscal +#define BLAS_COPY_ROUTINE cblas_zcopy +#define BLAS_DECLARE_SCALAR(x) double x [2] +#define BLAS_ASSIGN(x,xr,xi) { x [0] = xr ; x [1] = xi ; } +#else +#define BLAS_GEMM_ROUTINE cblas_dgemm +#define BLAS_TRSM_ROUTINE cblas_dtrsm +#define BLAS_TRSV_ROUTINE cblas_dtrsv +#define BLAS_GEMV_ROUTINE cblas_dgemv +#define BLAS_GER_ROUTINE cblas_dger +#define BLAS_SCAL_ROUTINE cblas_dscal +#define BLAS_COPY_ROUTINE cblas_dcopy +#define BLAS_DECLARE_SCALAR(x) double x +#define BLAS_ASSIGN(x,xr,xi) { x = xr ; } +#endif + +#define BLAS_LOWER CblasLower +#define BLAS_UNIT_DIAGONAL CblasUnit +#define BLAS_RIGHT CblasRight +#define BLAS_NO_TRANSPOSE CblasNoTrans +#define BLAS_TRANSPOSE CblasTrans +#define BLAS_COLUMN_MAJOR_ORDER CblasColMajor, +#define BLAS_SCALAR(x) x +#define BLAS_INT_SCALAR(n) n +#define BLAS_ARRAY(a) a + + + +/* -------------------------------------------------------------------------- */ +#else /* } USE_C_BLAS { */ +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +/* use Fortran (or other architecture-specific) BLAS */ +/* -------------------------------------------------------------------------- */ + +/* No such argument when not using the C-BLAS */ +#define BLAS_COLUMN_MAJOR_ORDER + +/* Determine which architecture we're on and set options accordingly. */ +/* The default, if nothing is defined is to add an underscore, */ +/* pass scalars by reference, and use string arguments. */ + +/* ---------------------------------- */ +/* Sun Performance BLAS */ +/* ---------------------------------- */ + +#ifdef USE_SUNPERF_BLAS +#ifdef _SUNPERF_H +/* has been included somehow anyway, outside of umf_config.h */ +#error "sunperf.h must NOT be #include'd. See umf_config.h for details." +#endif +#define BLAS_BY_VALUE +#define BLAS_NO_UNDERSCORE +#define BLAS_CHAR_ARG +#endif /* USE_SUNPERF_BLAS */ + +/* ---------------------------------- */ +/* SGI SCSL BLAS */ +/* ---------------------------------- */ + +#ifdef USE_SCSL_BLAS +#if defined (LP64) +#include +#else +#include +#endif +#define BLAS_BY_VALUE +#define BLAS_NO_UNDERSCORE +#endif /* USE_SCSL_BLAS */ + +/* ---------------------------------- */ +/* IBM AIX, Windows, and HP Fortran BLAS */ +/* ---------------------------------- */ + +#if defined (UMF_AIX) || defined (UMF_WINDOWS) || defined (UMF_HP) +#define BLAS_NO_UNDERSCORE +#endif + + +/* -------------------------------------------------------------------------- */ +/* BLAS names */ +/* -------------------------------------------------------------------------- */ + +#if defined (LP64) && defined (USE_SUNPERF_BLAS) && defined (LONG_INTEGER) + +/* 64-bit sunperf BLAS, for Sun Solaris only */ +#ifdef COMPLEX +#define BLAS_GEMM_ROUTINE zgemm_64 +#define BLAS_TRSM_ROUTINE ztrsm_64 +#define BLAS_TRSV_ROUTINE ztrsv_64 +#define BLAS_GEMV_ROUTINE zgemv_64 +#define BLAS_GER_ROUTINE zgeru_64 +#define BLAS_SCAL_ROUTINE zscal_64 +#define BLAS_COPY_ROUTINE zcopy_64 +#else +#define BLAS_GEMM_ROUTINE dgemm_64 +#define BLAS_TRSM_ROUTINE dtrsm_64 +#define BLAS_TRSV_ROUTINE dtrsv_64 +#define BLAS_GEMV_ROUTINE dgemv_64 +#define BLAS_GER_ROUTINE dger_64 +#define BLAS_SCAL_ROUTINE dscal_64 +#define BLAS_COPY_ROUTINE dcopy_64 +#endif /* COMPLEX */ + +#else + +#ifdef COMPLEX + +/* naming convention (use underscore, or not) */ +#ifdef BLAS_NO_UNDERSCORE +#define BLAS_GEMM_ROUTINE zgemm +#define BLAS_TRSM_ROUTINE ztrsm +#define BLAS_TRSV_ROUTINE ztrsv +#define BLAS_GEMV_ROUTINE zgemv +#define BLAS_GER_ROUTINE zgeru +#define BLAS_SCAL_ROUTINE zscal +#define BLAS_COPY_ROUTINE zcopy +#else +/* default: add underscore */ +#define BLAS_GEMM_ROUTINE zgemm_ +#define BLAS_TRSM_ROUTINE ztrsm_ +#define BLAS_TRSV_ROUTINE ztrsv_ +#define BLAS_GEMV_ROUTINE zgemv_ +#define BLAS_GER_ROUTINE zgeru_ +#define BLAS_SCAL_ROUTINE zscal_ +#define BLAS_COPY_ROUTINE zcopy_ +#endif + +#else + +/* naming convention (use underscore, or not) */ +#ifdef BLAS_NO_UNDERSCORE +#define BLAS_GEMM_ROUTINE dgemm +#define BLAS_TRSM_ROUTINE dtrsm +#define BLAS_TRSV_ROUTINE dtrsv +#define BLAS_GEMV_ROUTINE dgemv +#define BLAS_GER_ROUTINE dger +#define BLAS_SCAL_ROUTINE dscal +#define BLAS_COPY_ROUTINE dcopy +#else +/* default: add underscore */ +#define BLAS_GEMM_ROUTINE dgemm_ +#define BLAS_TRSM_ROUTINE dtrsm_ +#define BLAS_TRSV_ROUTINE dtrsv_ +#define BLAS_GEMV_ROUTINE dgemv_ +#define BLAS_GER_ROUTINE dger_ +#define BLAS_SCAL_ROUTINE dscal_ +#define BLAS_COPY_ROUTINE dcopy_ +#endif + +#endif /* COMPLEX */ + +#endif /* LP64 && USE_SUNPERF_BLAS */ + + +/* -------------------------------------------------------------------------- */ +/* BLAS real or complex floating-point scalars */ +/* -------------------------------------------------------------------------- */ + +#ifdef COMPLEX + +/* + The SunPerf BLAS expects to see a doublecomplex scalar, but it + also will accept an array of size 2. See the manual, normally at + file:///opt/SUNWspro/WS6U1/lib/locale/C/html/manuals/perflib/user_guide + /plug_using_perflib.html . This manual is inconsistent with the man pages + for zgemm, zgemv, and zgeru and also inconsistent with the + include file. Use this instead, for SunPerf (only works if you do NOT + include sunperf.h). Fortunately, this file (umf_config.h) is not included + in any user code that calls UMFPACK. Thus, the caller may include + sunperf.h in his or her own code, and that is safely ignored here. + SGI's SCSL BLAS has yet a different kind of struct, but we can use a + double array of size 2 instead (since SCSL_VOID_ARGS is defined). + Most BLAS expect complex scalars as pointers to double arrays of size 2. +*/ + +#define BLAS_DECLARE_SCALAR(x) double x [2] +#define BLAS_ASSIGN(x,xr,xi) { x [0] = xr ; x [1] = xi ; } +#define BLAS_SCALAR(x) x + +#else + +#define BLAS_DECLARE_SCALAR(x) double x +#define BLAS_ASSIGN(x,xr,xi) { x = xr ; } +#ifdef BLAS_BY_VALUE +#define BLAS_SCALAR(x) x +#else +#define BLAS_SCALAR(x) &(x) +#endif + +#endif /* COMPLEX */ + + +/* -------------------------------------------------------------------------- */ +/* BLAS integer scalars */ +/* -------------------------------------------------------------------------- */ + +/* + Fortran requires integers to be passed by reference. + The SCSL BLAS requires long long arguments in LP64 mode. +*/ + +#if defined (USE_SCSL_BLAS) && defined (LP64) +#define BLAS_INT_SCALAR(n) ((long long) n) +#else +#ifdef BLAS_BY_VALUE +#define BLAS_INT_SCALAR(n) n +#else +#define BLAS_INT_SCALAR(n) &(n) +#endif +#endif + + +/* -------------------------------------------------------------------------- */ +/* BLAS strings */ +/* -------------------------------------------------------------------------- */ + +/* + The Sun Performance BLAS wants a character instead of a string. +*/ + +#ifdef BLAS_CHAR_ARG +#define BLAS_NO_TRANSPOSE 'N' +#define BLAS_TRANSPOSE 'T' +#define BLAS_LEFT 'L' +#define BLAS_RIGHT 'R' +#define BLAS_LOWER 'L' +#define BLAS_UNIT_DIAGONAL 'U' +#else +#define BLAS_NO_TRANSPOSE "N" +#define BLAS_TRANSPOSE "T" +#define BLAS_LEFT "L" +#define BLAS_RIGHT "R" +#define BLAS_LOWER "L" +#define BLAS_UNIT_DIAGONAL "U" +#endif + + +/* -------------------------------------------------------------------------- */ +/* BLAS arrays */ +/* -------------------------------------------------------------------------- */ + +/* + The complex SunPerf BLAS expects to see a doublecomplex array of size s. + This is broken (see above, regarding complex scalars in sunperf.h). + For SunPerf BLAS, just pass a pointer to the array, and ignore sunperf.h. + With sunperf.h, you would need: + + #define BLAS_ARRAY(a) ((doublecomplex *)(a)) + + SGI's SCSL BLAS has yet a different kind of struct, but we can use a + double array of size 2 instead (since SCSL_VOID_ARGS is defined). + + The real versions all use just a (double *) pointer. + + In all cases, no typecast is required. This will break if is + included. + + If you have read this far, I hope you see now why (void *) a much better + choice for complex BLAS prototypes, and why double x [2] is better than + an architecture dependent struct { double real ; double imag ; } + type definition. + +*/ + +#define BLAS_ARRAY(a) (a) + + +/* -------------------------------------------------------------------------- */ +#endif /* USE_C_BLAS } */ +/* -------------------------------------------------------------------------- */ + + + + + +/* -------------------------------------------------------------------------- */ +/* BLAS macros, for all interfaces */ +/* -------------------------------------------------------------------------- */ + +/* + All architecture dependent issues have now been taken into consideration, + and folded into the macros BLAS_DECLARE_SCALAR, BLAS_ASSIGN, BLAS_*_ROUTINE, + BLAS_COLUMN_MAJOR_ORDER, BLAS_NO_TRANSPOSE, BLAS_TRANSPOSE, BLAS_SCALAR, + BLAS_INT_SCALAR, BLAS_ARRAY, and Int. + + You will note that there is not a *** single *** name, declaration, or + argument to the BLAS which is not somehow different in one or more versions + of the BLAS! +*/ + + +/* C = C - A*B', where: + * A is m-by-k with leading dimension ldac + * B is k-by-n with leading dimension ldb + * C is m-by-n with leading dimension ldac */ +#define BLAS_GEMM(m,n,k,A,B,ldb,C,ldac) \ +{ \ + BLAS_DECLARE_SCALAR (alpha) ; \ + BLAS_DECLARE_SCALAR (beta) ; \ + BLAS_ASSIGN (alpha, -1.0, 0.0) ; \ + BLAS_ASSIGN (beta, 1.0, 0.0) ; \ + (void) BLAS_GEMM_ROUTINE (BLAS_COLUMN_MAJOR_ORDER \ + BLAS_NO_TRANSPOSE, BLAS_TRANSPOSE, \ + BLAS_INT_SCALAR (m), BLAS_INT_SCALAR (n), BLAS_INT_SCALAR (k), \ + BLAS_SCALAR (alpha), \ + BLAS_ARRAY (A), BLAS_INT_SCALAR (ldac), \ + BLAS_ARRAY (B), BLAS_INT_SCALAR (ldb), BLAS_SCALAR (beta), \ + BLAS_ARRAY (C), BLAS_INT_SCALAR (ldac)) ; \ +} + +/* A = A - x*y', where: + * A is m-by-n with leading dimension d + x is a column vector with stride 1 + y is a column vector with stride 1 */ +#define BLAS_GER(m,n,x,y,A,d) \ +{ \ + Int one = 1 ; \ + BLAS_DECLARE_SCALAR (alpha) ; \ + BLAS_ASSIGN (alpha, -1.0, 0.0) ; \ + (void) BLAS_GER_ROUTINE (BLAS_COLUMN_MAJOR_ORDER \ + BLAS_INT_SCALAR (m), BLAS_INT_SCALAR (n), \ + BLAS_SCALAR (alpha), \ + BLAS_ARRAY (x), BLAS_INT_SCALAR (one), \ + BLAS_ARRAY (y), BLAS_INT_SCALAR (one), \ + BLAS_ARRAY (A), BLAS_INT_SCALAR (d)) ; \ +} + +/* y = y - A*x, where A is m-by-n with leading dimension d, + x is a column vector with stride 1 + y is a column vector with stride 1 */ +#define BLAS_GEMV(m,n,A,x,y,d) \ +{ \ + Int one = 1 ; \ + BLAS_DECLARE_SCALAR (alpha) ; \ + BLAS_DECLARE_SCALAR (beta) ; \ + BLAS_ASSIGN (alpha, -1.0, 0.0) ; \ + BLAS_ASSIGN (beta, 1.0, 0.0) ; \ + (void) BLAS_GEMV_ROUTINE (BLAS_COLUMN_MAJOR_ORDER \ + BLAS_NO_TRANSPOSE, \ + BLAS_INT_SCALAR (m), BLAS_INT_SCALAR (n), \ + BLAS_SCALAR (alpha), \ + BLAS_ARRAY (A), BLAS_INT_SCALAR (d), \ + BLAS_ARRAY (x), BLAS_INT_SCALAR (one), BLAS_SCALAR (beta), \ + BLAS_ARRAY (y), BLAS_INT_SCALAR (one)) ; \ +} + + +/* solve Lx=b, where: + * B is a column vector (m-by-1) with leading dimension d + * A is m-by-m with leading dimension d */ +#define BLAS_TRSV(m,A,b,d) \ +{ \ + Int one = 1 ; \ + (void) BLAS_TRSV_ROUTINE (BLAS_COLUMN_MAJOR_ORDER \ + BLAS_LOWER, BLAS_NO_TRANSPOSE, BLAS_UNIT_DIAGONAL, \ + BLAS_INT_SCALAR (m), \ + BLAS_ARRAY (A), BLAS_INT_SCALAR (d), \ + BLAS_ARRAY (b), BLAS_INT_SCALAR (one)) ; \ +} + +/* solve XL'=B where: + * B is m-by-n with leading dimension ldb + * A is n-by-n with leading dimension lda */ +#define BLAS_TRSM_RIGHT(m,n,A,lda,B,ldb) \ +{ \ + BLAS_DECLARE_SCALAR (alpha) ; \ + BLAS_ASSIGN (alpha, 1.0, 0.0) ; \ + (void) BLAS_TRSM_ROUTINE (BLAS_COLUMN_MAJOR_ORDER \ + BLAS_RIGHT, BLAS_LOWER, BLAS_TRANSPOSE, BLAS_UNIT_DIAGONAL, \ + BLAS_INT_SCALAR (m), BLAS_INT_SCALAR (n), \ + BLAS_SCALAR (alpha), \ + BLAS_ARRAY (A), BLAS_INT_SCALAR (lda), \ + BLAS_ARRAY (B), BLAS_INT_SCALAR (ldb)) ; \ +} + +/* x = s*x, where x is a stride-1 vector of length n */ +#define BLAS_SCAL(n,s,x) \ +{ \ + Int one = 1 ; \ + BLAS_DECLARE_SCALAR (alpha) ; \ + BLAS_ASSIGN (alpha, REAL_COMPONENT (s), IMAG_COMPONENT (s)) ; \ + (void) BLAS_SCAL_ROUTINE ( \ + BLAS_INT_SCALAR (n), BLAS_SCALAR (alpha), \ + BLAS_ARRAY (x), BLAS_INT_SCALAR (one)) ; \ +} + +/* x = y, where x and y are a stride-1 vectors of length n */ +#define BLAS_COPY(n,x,y) \ +{ \ + Int one = 1 ; \ + (void) BLAS_COPY_ROUTINE ( \ + BLAS_INT_SCALAR (n), \ + BLAS_ARRAY (x), BLAS_INT_SCALAR (one), \ + BLAS_ARRAY (y), BLAS_INT_SCALAR (one)) ; \ +} + +#endif /* !defined (USE_NO_BLAS) } */ diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.c b/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.c @@ -0,0 +1,604 @@ +/* ========================================================================== */ +/* === UMF_create_element =================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Factorization of a frontal matrix is complete. Create a new element for + later assembly into a subsequent frontal matrix. Returns TRUE if + successful, FALSE if out of memory. +*/ + +#include "umf_internal.h" +#include "umf_mem_alloc_element.h" +#include "umf_mem_alloc_tail_block.h" +#include "umf_mem_free_tail_block.h" +#include "umf_get_memory.h" + +/* ========================================================================== */ +/* === copy_column ========================================================== */ +/* ========================================================================== */ + +PRIVATE void copy_column (Int len, Entry *X, Entry *Y) +{ + Int i ; +#pragma ivdep + for (i = 0 ; i < len ; i++) + { + Y [i] = X [i] ; + } +} + +/* ========================================================================== */ +/* === UMF_create_element =================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMF_create_element +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int j, col, row, *Fcols, *Frows, fnrows, fncols, *Cols, len, needunits, t1, + t2, size, e, i, *E, *Fcpos, *Frpos, *Rows, eloc, fnr_curr, f, + got_memory, *Row_tuples, *Row_degree, *Row_tlen, *Col_tuples, max_mark, + *Col_degree, *Col_tlen, nn, n_row, n_col, r2, c2, do_Fcpos ; + Entry *C, *Fcol ; + Element *ep ; + Unit *p, *Memory ; + Tuple *tp, *tp1, *tp2, tuple, *tpend ; +#ifndef NDEBUG + DEBUG2 (("FRONTAL WRAPUP\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + ASSERT (Work->fnpiv == 0) ; + ASSERT (Work->fnzeros == 0) ; + Row_degree = Numeric->Rperm ; + Row_tuples = Numeric->Uip ; + Row_tlen = Numeric->Uilen ; + Col_degree = Numeric->Cperm ; + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + n_row = Work->n_row ; + n_col = Work->n_col ; + nn = MAX (n_row, n_col) ; + Fcols = Work->Fcols ; + Frows = Work->Frows ; + Fcpos = Work->Fcpos ; + Frpos = Work->Frpos ; + Memory = Numeric->Memory ; + fncols = Work->fncols ; + fnrows = Work->fnrows ; + + tp = (Tuple *) NULL ; + tp1 = (Tuple *) NULL ; + tp2 = (Tuple *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* add the current frontal matrix to the degrees of each column */ + /* ---------------------------------------------------------------------- */ + + if (!Symbolic->fixQ) + { + /* but only if the column ordering is not fixed */ +#pragma ivdep + for (j = 0 ; j < fncols ; j++) + { + /* add the current frontal matrix to the degree */ + ASSERT (Fcols [j] >= 0 && Fcols [j] < n_col) ; + Col_degree [Fcols [j]] += fnrows ; + } + } + + /* ---------------------------------------------------------------------- */ + /* add the current frontal matrix to the degrees of each row */ + /* ---------------------------------------------------------------------- */ + +#pragma ivdep + for (i = 0 ; i < fnrows ; i++) + { + /* add the current frontal matrix to the degree */ + ASSERT (Frows [i] >= 0 && Frows [i] < n_row) ; + Row_degree [Frows [i]] += fncols ; + } + + /* ---------------------------------------------------------------------- */ + /* Reset the external degree counters */ + /* ---------------------------------------------------------------------- */ + + E = Work->E ; + max_mark = MAX_MARK (nn) ; + + if (!Work->pivcol_in_front) + { + /* clear the external column degrees. no more Usons of current front */ + Work->cdeg0 += (nn + 1) ; + if (Work->cdeg0 >= max_mark) + { + /* guard against integer overflow. This is very rare */ + DEBUG1 (("Integer overflow, cdeg\n")) ; + Work->cdeg0 = 1 ; +#pragma ivdep + for (e = 1 ; e <= Work->nel ; e++) + { + if (E [e]) + { + ep = (Element *) (Memory + E [e]) ; + ep->cdeg = 0 ; + } + } + } + } + + if (!Work->pivrow_in_front) + { + /* clear the external row degrees. no more Lsons of current front */ + Work->rdeg0 += (nn + 1) ; + if (Work->rdeg0 >= max_mark) + { + /* guard against integer overflow. This is very rare */ + DEBUG1 (("Integer overflow, rdeg\n")) ; + Work->rdeg0 = 1 ; +#pragma ivdep + for (e = 1 ; e <= Work->nel ; e++) + { + if (E [e]) + { + ep = (Element *) (Memory + E [e]) ; + ep->rdeg = 0 ; + } + } + } + } + + /* ---------------------------------------------------------------------- */ + /* clear row/col offsets */ + /* ---------------------------------------------------------------------- */ + + if (!Work->pivrow_in_front) + { +#pragma ivdep + for (j = 0 ; j < fncols ; j++) + { + Fcpos [Fcols [j]] = EMPTY ; + } + } + + if (!Work->pivcol_in_front) + { +#pragma ivdep + for (i = 0 ; i < fnrows ; i++) + { + Frpos [Frows [i]] = EMPTY ; + } + } + + if (fncols <= 0 || fnrows <= 0) + { + /* no element to create */ + DEBUG2 (("Element evaporation\n")) ; + Work->prior_element = EMPTY ; + return (TRUE) ; + } + + /* ---------------------------------------------------------------------- */ + /* create element for later assembly */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) + { + double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ; + DEBUG4 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random garbage collection (create)\n")); + } +#endif + + needunits = 0 ; + got_memory = FALSE ; + eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C, + &needunits, &ep) ; + + /* if UMF_get_memory needs to be called */ + if (Work->do_grow) + { + /* full compaction of current frontal matrix, since UMF_grow_front will + * be called next anyway. */ + r2 = fnrows ; + c2 = fncols ; + do_Fcpos = FALSE ; + } + else + { + /* partial compaction. */ + r2 = MAX (fnrows, Work->fnrows_new + 1) ; + c2 = MAX (fncols, Work->fncols_new + 1) ; + /* recompute Fcpos if pivot row is in the front */ + do_Fcpos = Work->pivrow_in_front ; + } + + if (!eloc) + { + /* Do garbage collection, realloc, and try again. */ + /* Compact the current front if it needs to grow anyway. */ + /* Note that there are no pivot rows or columns in the current front */ + DEBUGm3 (("get_memory from umf_create_element, 1\n")) ; + if (!UMF_get_memory (Numeric, Work, needunits, r2, c2, do_Fcpos)) + { + /* :: out of memory in umf_create_element (1) :: */ + DEBUGm4 (("out of memory: create element (1)\n")) ; + return (FALSE) ; /* out of memory */ + } + got_memory = TRUE ; + Memory = Numeric->Memory ; + eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C, + &needunits, &ep) ; + ASSERT (eloc >= 0) ; + if (!eloc) + { + /* :: out of memory in umf_create_element (2) :: */ + DEBUGm4 (("out of memory: create element (2)\n")) ; + return (FALSE) ; /* out of memory */ + } + } + + e = ++(Work->nel) ; /* get the name of this new frontal matrix */ + Work->prior_element = e ; + DEBUG8 (("wrapup e "ID" nel "ID"\n", e, Work->nel)) ; + + ASSERT (e > 0 && e < Work->elen) ; + ASSERT (E [e] == 0) ; + E [e] = eloc ; + + if (Work->pivcol_in_front) + { + /* the new element is a Uson of the next frontal matrix */ + ep->cdeg = Work->cdeg0 ; + } + + if (Work->pivrow_in_front) + { + /* the new element is an Lson of the next frontal matrix */ + ep->rdeg = Work->rdeg0 ; + } + + /* ---------------------------------------------------------------------- */ + /* copy frontal matrix into the new element */ + /* ---------------------------------------------------------------------- */ + +#pragma ivdep + for (i = 0 ; i < fnrows ; i++) + { + Rows [i] = Frows [i] ; + } +#pragma ivdep + for (i = 0 ; i < fncols ; i++) + { + Cols [i] = Fcols [i] ; + } + Fcol = Work->Fcblock ; + DEBUG0 (("copy front "ID" by "ID"\n", fnrows, fncols)) ; + fnr_curr = Work->fnr_curr ; + ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ; + for (j = 0 ; j < fncols ; j++) + { + copy_column (fnrows, Fcol, C) ; +#if 0 +#ifdef USE_NO_BLAS + copy_column (fnrows, Fcol, C) ; +#else + could also use BLAS-COPY (fnrows, Fcol, C) here, but it is typically + not as fast as the inlined copy_column subroutine, above. +#endif + for (i = 0 ; i < fnrows ; i++) + { + C [i] = Fcol [i] ; + } +#endif + Fcol += fnr_curr ; + C += fnrows ; + } + + DEBUG8 (("element copied\n")) ; + + /* ---------------------------------------------------------------------- */ + /* add tuples for the new element */ + /* ---------------------------------------------------------------------- */ + + tuple.e = e ; + + if (got_memory) + { + + /* ------------------------------------------------------------------ */ + /* UMF_get_memory ensures enough space exists for each new tuple */ + /* ------------------------------------------------------------------ */ + + /* place (e,f) in the element list of each column */ + for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++) + { + col = Fcols [tuple.f] ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + ASSERT (Col_tuples [col]) ; + tp = ((Tuple *) (Memory + Col_tuples [col])) + Col_tlen [col]++ ; + *tp = tuple ; + } + + /* ------------------------------------------------------------------ */ + + /* place (e,f) in the element list of each row */ + for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++) + { + row = Frows [tuple.f] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (NON_PIVOTAL_ROW (row)) ; + ASSERT (Row_tuples [row]) ; + tp = ((Tuple *) (Memory + Row_tuples [row])) + Row_tlen [row]++ ; + *tp = tuple ; + } + + } + else + { + + /* ------------------------------------------------------------------ */ + /* place (e,f) in the element list of each column */ + /* ------------------------------------------------------------------ */ + + /* might not have enough space for each tuple */ + + for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++) + { + col = Fcols [tuple.f] ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + t1 = Col_tuples [col] ; + DEBUG1 (("Placing on col:"ID" , tuples at "ID"\n", + col, Col_tuples [col])) ; + + size = 0 ; + len = 0 ; + + if (t1) + { + p = Memory + t1 ; + tp = (Tuple *) p ; + size = GET_BLOCK_SIZE (p) ; + len = Col_tlen [col] ; + tp2 = tp + len ; + } + + needunits = UNITS (Tuple, len + 1) ; + DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n", + len, size, needunits)); + + if (needunits > size && t1) + { + /* prune the tuples */ + tp1 = tp ; + tp2 = tp ; + tpend = tp + len ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + ; + if (Cols [f] == EMPTY) continue ; /* already assembled */ + ASSERT (col == Cols [f]) ; + *tp2++ = *tp ; /* leave the tuple in the list */ + } + len = tp2 - tp1 ; + Col_tlen [col] = len ; + needunits = UNITS (Tuple, len + 1) ; + } + + if (needunits > size) + { + /* no room exists - reallocate elsewhere */ + DEBUG1 (("REALLOCATE Col: "ID", size "ID" to "ID"\n", + col, size, 2*needunits)) ; + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) /* a double relop, but ignore NaN case */ + { + double rrr = ((double) (rand ( ))) / + (((double) RAND_MAX) + 1) ; + DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random gar. (col tuple)\n")) ; + } +#endif + + needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ; + t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ; + if (!t2) + { + /* :: get memory in umf_create_element (1) :: */ + /* get memory, reconstruct all tuple lists, and return */ + /* Compact the current front if it needs to grow anyway. */ + /* Note: no pivot rows or columns in the current front */ + DEBUGm4 (("get_memory from umf_create_element, 1\n")) ; + return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos)); + } + Col_tuples [col] = t2 ; + tp2 = (Tuple *) (Memory + t2) ; + if (t1) + { + for (i = 0 ; i < len ; i++) + { + *tp2++ = *tp1++ ; + } + UMF_mem_free_tail_block (Numeric, t1) ; + } + } + + /* place the new (e,f) tuple in the element list of the column */ + Col_tlen [col]++ ; + *tp2 = tuple ; + } + + /* ------------------------------------------------------------------ */ + /* place (e,f) in the element list of each row */ + /* ------------------------------------------------------------------ */ + + for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++) + { + row = Frows [tuple.f] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (NON_PIVOTAL_ROW (row)) ; + t1 = Row_tuples [row] ; + DEBUG1 (("Placing on row:"ID" , tuples at "ID"\n", + row, Row_tuples [row])) ; + + size = 0 ; + len = 0 ; + if (t1) + { + p = Memory + t1 ; + tp = (Tuple *) p ; + size = GET_BLOCK_SIZE (p) ; + len = Row_tlen [row] ; + tp2 = tp + len ; + } + + needunits = UNITS (Tuple, len + 1) ; + DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n", + len, size, needunits)) ; + + if (needunits > size && t1) + { + /* prune the tuples */ + tp1 = tp ; + tp2 = tp ; + tpend = tp + len ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) + { + continue ; /* element already deallocated */ + } + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + Rows = Cols + (ep->ncols) ; + if (Rows [f] == EMPTY) continue ; /* already assembled */ + ASSERT (row == Rows [f]) ; + *tp2++ = *tp ; /* leave the tuple in the list */ + } + len = tp2 - tp1 ; + Row_tlen [row] = len ; + needunits = UNITS (Tuple, len + 1) ; + } + + if (needunits > size) + { + /* no room exists - reallocate elsewhere */ + DEBUG1 (("REALLOCATE Row: "ID", size "ID" to "ID"\n", + row, size, 2*needunits)) ; + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) /* a double relop, but ignore NaN case */ + { + double rrr = ((double) (rand ( ))) / + (((double) RAND_MAX) + 1) ; + DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random gar. (row tuple)\n")) ; + } +#endif + + needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ; + t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ; + if (!t2) + { + /* :: get memory in umf_create_element (2) :: */ + /* get memory, reconstruct all tuple lists, and return */ + /* Compact the current front if it needs to grow anyway. */ + /* Note: no pivot rows or columns in the current front */ + DEBUGm4 (("get_memory from umf_create_element, 2\n")) ; + return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos)); + } + Row_tuples [row] = t2 ; + tp2 = (Tuple *) (Memory + t2) ; + if (t1) + { + for (i = 0 ; i < len ; i++) + { + *tp2++ = *tp1++ ; + } + UMF_mem_free_tail_block (Numeric, t1) ; + } + } + + /* place the new (e,f) tuple in the element list of the row */ + Row_tlen [row]++ ; + *tp2 = tuple ; + } + + } + + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG1 (("Done extending\nFINAL: element row pattern: len="ID"\n", fncols)); + for (j = 0 ; j < fncols ; j++) DEBUG1 ((""ID"\n", Fcols [j])) ; + DEBUG1 (("FINAL: element col pattern: len="ID"\n", fnrows)) ; + for (j = 0 ; j < fnrows ; j++) DEBUG1 ((""ID"\n", Frows [j])) ; + for (j = 0 ; j < fncols ; j++) + { + col = Fcols [j] ; + ASSERT (col >= 0 && col < n_col) ; + UMF_dump_rowcol (1, Numeric, Work, col, !Symbolic->fixQ) ; + } + for (j = 0 ; j < fnrows ; j++) + { + row = Frows [j] ; + ASSERT (row >= 0 && row < n_row) ; + UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ; + } + if (n_row < 1000 && n_col < 1000) + { + UMF_dump_memory (Numeric) ; + } + DEBUG1 (("New element, after filling with stuff: "ID"\n", e)) ; + UMF_dump_element (Numeric, Work, e, TRUE) ; + if (nn < 1000) + { + DEBUG4 (("Matrix dump, after New element: "ID"\n", e)) ; + UMF_dump_matrix (Numeric, Work, TRUE) ; + } + DEBUG3 (("FRONTAL WRAPUP DONE\n")) ; +#endif + + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.h b/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_create_element.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_create_element +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_dump.c b/liboctave/UMFPACK/UMFPACK/Source/umf_dump.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_dump.c @@ -0,0 +1,1225 @@ +/* ========================================================================== */ +/* === UMF_dump ============================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* These routines, and external variables, are used only when debugging. */ +/* If debugging is disabled (for normal operation) then this entire file */ +/* becomes empty */ + +#include "umf_internal.h" + +#ifndef NDEBUG + +/* These global debugging variables and arrays do not exist if debugging */ +/* is disabled at compile time (which is the default). */ +GLOBAL Int UMF_debug = -999 ; +GLOBAL Int UMF_allocfail = FALSE ; +GLOBAL double UMF_gprob = -1.0 ; + +/* static debugging arrays used only in UMF_dump_rowcol */ +PRIVATE Int UMF_DBflag = 0 ; +PRIVATE Int UMF_DBpacked [UMF_DBMAX+1] ; +PRIVATE Int UMF_DBscatter [UMF_DBMAX+1] ; + +/* ========================================================================== */ +/* === UMF_DBinit =========================================================== */ +/* ========================================================================== */ + +/* clear the debugging arrays */ + +PRIVATE void UMF_DBinit +( + void +) +{ + Int i ; + + /* Int_MAX is defined in umfpack.h */ + if (UMF_DBflag < 1 || UMF_DBflag == Int_MAX) + { + /* clear the debugging arrays */ + UMF_DBflag = 0 ; + for (i = 0 ; i <= UMF_DBMAX ; i++) + { + UMF_DBscatter [i] = 0 ; + UMF_DBpacked [i] = 0 ; + } + } + + UMF_DBflag++ ; + + /* UMF_DBflag > UMF_DBscatter [0...UMF_DBmax] is now true */ +} + +/* ========================================================================== */ +/* === UMF_dump_dense ======================================================= */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_dense +( + Entry *C, + Int dim, + Int m, + Int n +) +{ + + /* dump C [1..m,1..n], with column dimenstion dim */ + Int i, j; + + if (UMF_debug < 7) return ; + if (C == (Entry *) NULL) + { + DEBUG7 (("No dense matrix allocated\n")) ; + return ; + } + DEBUG8 ((" dimension= "ID" rows= "ID" cols= "ID"\n", dim, m, n)) ; + + for (i = 0 ; i < m ; i++) + { + DEBUG9 ((ID": ", i)) ; + for (j = 0 ; j < n ; j++) + { + EDEBUG9 (C [i+j*dim]) ; + if (j % 6 == 5) DEBUG9 (("\n ")) ; + } + DEBUG9 (("\n")) ; + } + + for (i = 0 ; i < m ; i++) + { + for (j = 0 ; j < n ; j++) + { + if (IS_ZERO (C [i+j*dim])) + { + DEBUG8 ((".")) ; + } + else + { + DEBUG8 (("X")) ; + } + } + DEBUG8 (("\n")) ; + } +} + +/* ========================================================================== */ +/* === UMF_dump_element ===================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_element +( + NumericType *Numeric, + WorkType *Work, + Int e, + Int clean +) +{ + + Int i, j, k, *Rows, *Cols, nrows, ncols, *E, row, col, + *Row_degree, *Col_degree ; + Entry *C ; + Element *ep ; + Unit *p ; + + if (UMF_debug < 7) return ; + + if (e == 0) + { + UMF_dump_current_front (Numeric, Work, FALSE) ; + return ; + } + + DEBUG7 (("\n====================ELEMENT: "ID" ", e)) ; + if (!Numeric || !Work || !Numeric->Memory) + { + DEBUG7 ((" No Numeric, Work\n")) ; + return ; + } + DEBUG7 ((" nel: "ID" of "ID, e, Work->nel)) ; + E = Work->E ; + if (!E) + { + DEBUG7 ((" No elements\n")) ; + return ; + } + if (e < 0 || e > Work->nel) + { + DEBUG7 (("e out of range!\n")) ; + return ; + } + if (!E [e]) + { + DEBUG7 ((" deallocated\n")) ; + return ; + } + DEBUG7 (("\n")) ; + Col_degree = Numeric->Cperm ; + Row_degree = Numeric->Rperm ; + + p = Numeric->Memory + E [e] ; + DEBUG7 (("ep "ID"\n", (Int) (p-Numeric->Memory))) ; + GET_ELEMENT (ep, p, Cols, Rows, ncols, nrows, C) ; + DEBUG7 (("nrows "ID" nrowsleft "ID"\n", nrows, ep->nrowsleft)) ; + DEBUG7 (("ncols "ID" ncolsleft "ID"\n", ncols, ep->ncolsleft)) ; + DEBUG7 (("cdeg-cdeg0 "ID" rdeg-rdeg0 "ID" next "ID"\n", + ep->cdeg - Work->cdeg0, ep->rdeg - Work->rdeg0, ep->next)) ; + + DEBUG8 (("rows: ")) ; + k = 0 ; + for (i = 0 ; i < ep->nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) + { + DEBUG8 ((" "ID, row)) ; + ASSERT (row < Work->n_row) ; + if ((k++ % 10) == 9) DEBUG8 (("\n")) ; + ASSERT (IMPLIES (clean, NON_PIVOTAL_ROW (row))) ; + } + } + + DEBUG8 (("\ncols: ")) ; + k = 0 ; + for (j = 0 ; j < ep->ncols ; j++) + { + col = Cols [j] ; + if (col >= 0) + { + DEBUG8 ((" "ID, col)) ; + ASSERT (col < Work->n_col) ; + if ((k++ % 10) == 9) DEBUG8 (("\n")) ; + ASSERT (IMPLIES (clean, NON_PIVOTAL_COL (col))) ; + } + } + + DEBUG8 (("\nvalues:\n")) ; + if (UMF_debug >= 9) + { + for (i = 0 ; i < ep->nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) + { + DEBUG9 ((ID": ", row)) ; + k = 0 ; + for (j = 0 ; j < ep->ncols ; j++) + { + col = Cols [j] ; + if (col >= 0) + { + EDEBUG9 (C [i+j*ep->nrows]) ; + if (k++ % 6 == 5) DEBUG9 (("\n ")) ; + } + } + DEBUG9 (("\n")) ; + } + } + } + + DEBUG7 (("====================\n")) ; +} + + +/* ========================================================================== */ +/* === UMF_dump_rowcol ====================================================== */ +/* ========================================================================== */ + +/* dump a row or a column, from one or more memory spaces */ +/* return exact degree */ + +GLOBAL void UMF_dump_rowcol +( + Int dumpwhich, /* 0 for row, 1 for column */ + NumericType *Numeric, + WorkType *Work, + Int dumpindex, /* row or column index to dump */ + Int check_degree /* true if degree is to be checked */ +) +{ + Entry value ; + Entry *C ; + Int f, nrows, j, jj, len, e, deg, index, n_row, n_col, *Cols, *Rows, nn, + dumpdeg, ncols, preve, *E, tpi, *Pattern, approx_deg, not_in_use ; + Tuple *tp, *tend ; + Element *ep ; + Int *Row_tuples, *Row_degree, *Row_tlen ; + Int *Col_tuples, *Col_degree, *Col_tlen ; + Unit *p ; + Int is_there ; + + /* clear the debugging arrays */ + UMF_DBinit () ; + + if (dumpwhich == 0) + { + DEBUG7 (("\n====================ROW: "ID, dumpindex)) ; + } + else + { + DEBUG7 (("\n====================COL: "ID, dumpindex)) ; + } + + if (dumpindex == EMPTY) + { + DEBUG7 ((" (EMPTY)\n")) ; + return ; + } + + deg = 0 ; + approx_deg = 0 ; + + if (!Numeric || !Work) + { + DEBUG7 ((" No Numeric, Work\n")) ; + return ; + } + + n_row = Work->n_row ; + n_col = Work->n_col ; + nn = MAX (n_row, n_col) ; + E = Work->E ; + + Col_degree = Numeric->Cperm ; + Row_degree = Numeric->Rperm ; + + Row_tuples = Numeric->Uip ; + Row_tlen = Numeric->Uilen ; + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + + if (!E + || !Row_tuples || !Row_degree || !Row_tlen + || !Col_tuples || !Col_degree || !Col_tlen) + { + DEBUG7 ((" No E, Rows, Cols\n")) ; + return ; + } + + if (dumpwhich == 0) + { + /* dump a row */ + ASSERT (dumpindex >= 0 && dumpindex < n_row) ; + if (!NON_PIVOTAL_ROW (dumpindex)) + { + DEBUG7 ((" Pivotal\n")) ; + return ; + } + len = Row_tlen [dumpindex] ; + dumpdeg = Row_degree [dumpindex] ; + tpi = Row_tuples [dumpindex] ; + } + else + { + /* dump a column */ + ASSERT (dumpindex >= 0 && dumpindex < n_col) ; + if (!NON_PIVOTAL_COL (dumpindex)) + { + DEBUG7 ((" Pivotal\n")) ; + return ; + } + len = Col_tlen [dumpindex] ; + dumpdeg = Col_degree [dumpindex] ; + tpi = Col_tuples [dumpindex] ; + } + + p = Numeric->Memory + tpi ; + tp = (Tuple *) p ; + if (!tpi) + { + DEBUG7 ((" Nonpivotal, No tuple list tuples "ID" tlen "ID"\n", + tpi, len)) ; + return ; + } + ASSERT (p >= Numeric->Memory + Numeric->itail) ; + ASSERT (p < Numeric->Memory + Numeric->size) ; + + DEBUG7 ((" degree: "ID" len: "ID"\n", dumpdeg, len)) ; + not_in_use = (p-1)->header.size - UNITS (Tuple, len) ; + DEBUG7 ((" Tuple list: p+1: "ID" size: "ID" units, "ID" not in use\n", + (Int) (p-Numeric->Memory), (p-1)->header.size, not_in_use)) ; + ASSERT (not_in_use >= 0) ; + tend = tp + len ; + preve = 0 ; + for ( ; tp < tend ; tp++) + { + /* row/col of element e, offset is f: */ + /* DEBUG8 ((" (tp="ID")\n", tp)) ; */ + e = tp->e ; + f = tp->f ; + DEBUG8 ((" (e="ID", f="ID")\n", e, f)) ; + ASSERT (e > 0 && e <= Work->nel) ; + /* dump the pattern and values */ + if (E [e]) + { + p = Numeric->Memory + E [e] ; + GET_ELEMENT (ep, p, Cols, Rows, ncols, nrows, C) ; + if (dumpwhich == 0) + { + Pattern = Cols ; + jj = ep->ncols ; + is_there = Rows [f] >= 0 ; + if (is_there) approx_deg += ep->ncolsleft ; + } + else + { + Pattern = Rows ; + jj = ep->nrows ; + is_there = Cols [f] >= 0 ; + if (is_there) approx_deg += ep->nrowsleft ; + } + if (!is_there) + { + DEBUG8 (("\t\tnot present\n")) ; + } + else + { + for (j = 0 ; j < jj ; j++) + { + index = Pattern [j] ; + value = + C [ (dumpwhich == 0) ? (f+nrows*j) : (j+nrows*f) ] ; + if (index >= 0) + { + DEBUG8 (("\t\t"ID":", index)) ; + EDEBUG8 (value) ; + DEBUG8 (("\n")) ; + if (dumpwhich == 0) + { + /* col must be in the range 0..n_col-1 */ + ASSERT (index < n_col) ; + } + else + { + /* row must be in the range 0..n_row-1 */ + ASSERT (index < n_row) ; + } + + if (nn <= UMF_DBMAX) + { + if (UMF_DBscatter [index] != UMF_DBflag) + { + UMF_DBpacked [deg++] = index ; + UMF_DBscatter [index] = UMF_DBflag ; + } + } + } + } + } + /* the (e,f) tuples should be in order of their creation */ + /* this means that garbage collection will not jumble them */ + ASSERT (preve < e) ; + preve = e ; + } + else + { + DEBUG8 (("\t\tdeallocated\n")) ; + } + } + + if (nn <= UMF_DBMAX) + { + if (deg > 0) + { + DEBUG7 ((" Assembled, actual deg: "ID" : ", deg)) ; + for (j = 0 ; j < deg ; j++) + { + index = UMF_DBpacked [j] ; + DEBUG8 ((ID" ", index)) ; + if (j % 20 == 19) DEBUG8 (("\n ")) ; + ASSERT (UMF_DBscatter [index] == UMF_DBflag) ; + } + DEBUG7 (("\n")) ; + } + } + + /* Col_degree is not maintained when fixQ is true */ + if (check_degree) + { + DEBUG8 ((" approx_deg "ID" dumpdeg "ID"\n", approx_deg, dumpdeg)) ; + ASSERT (approx_deg == dumpdeg) ; + } + + DEBUG7 (("====================\n")) ; + + /* deg is now the exact degree */ + /* if nn <= UMF_DBMAX, then UMF_DBscatter [i] == UMF_DBflag for every i */ + /* in the row or col, and != UMF_DBflag if not */ + + return ; +} + + +/* ========================================================================== */ +/* === UMF_dump_matrix ====================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_matrix +( + NumericType *Numeric, + WorkType *Work, + Int check_degree +) +{ + + Int e, row, col, intfrag, frag, n_row, n_col, *E, fullsize, actualsize ; + Element *ep ; + Unit *p ; + + DEBUG6 (("=================================================== MATRIX:\n")) ; + if (!Numeric || !Work) + { + DEBUG6 (("No Numeric or Work allocated\n")) ; + return ; + } + if (!Numeric->Memory) + { + DEBUG6 (("No Numeric->Memory\n")) ; + return ; + } + + n_row = Work->n_row ; + n_col = Work->n_col ; + DEBUG6 (("n_row "ID" n_col "ID" nz "ID"\n", n_row, n_col, Work->nz)) ; + DEBUG6 (("============================ ELEMENTS: "ID" \n", Work->nel)) ; + intfrag = 0 ; + E = Work->E ; + if (!E) + { + DEBUG6 (("No elements allocated\n")) ; + } + else + { + for (e = 0 ; e <= Work->nel ; e++) + { + UMF_dump_element (Numeric, Work, e, FALSE) ; + if (e > 0 && E [e]) + { + p = Numeric->Memory + E [e] ; + ep = (Element *) p ; + ASSERT (ep->nrowsleft > 0 || ep->ncolsleft > 0) ; + fullsize = GET_BLOCK_SIZE (p) ; + actualsize = GET_ELEMENT_SIZE (ep->nrowsleft,ep->ncolsleft); + frag = fullsize - actualsize ; + intfrag += frag ; + DEBUG7 (("dump el: "ID", full "ID" actual "ID" frag: "ID + " intfrag: "ID"\n", e, fullsize, actualsize, frag, + intfrag)) ; + } + } + } + + DEBUG6 (("CURRENT INTERNAL FRAG in elements: "ID" \n", intfrag)) ; + + + + DEBUG6 (("======================================== ROWS: "ID"\n", n_row)) ; + UMF_debug -= 2 ; + for (row = 0 ; row < n_row ; row++) + { + UMF_dump_rowcol (0, Numeric, Work, row, check_degree) ; + } + UMF_debug += 2 ; + DEBUG6 (("======================================== COLS: "ID"\n", n_col)) ; + UMF_debug -= 2 ; + for (col = 0 ; col < n_col ; col++) + { + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; + } + UMF_debug += 2 ; + DEBUG6 (("============================================= END OF MATRIX:\n")); +} + + +/* ========================================================================== */ +/* === UMF_dump_current_front =============================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_current_front +( + NumericType *Numeric, + WorkType *Work, + Int check +) +{ + + Entry *Flublock, *Flblock, *Fublock, *Fcblock ; + Int fnrows_max, fncols_max, fnrows, fncols, fnpiv, *Frows, *Fcols, + i, j, *Fcpos, *Frpos, fnr_curr, fnc_curr, *E ; + if (!Work) return ; + DEBUG7 (("\n\n========CURRENT FRONTAL MATRIX:\n")) ; + + Flublock = Work->Flublock ; + Flblock = Work->Flblock ; + Fublock = Work->Fublock ; + Fcblock = Work->Fcblock ; + + Frows = Work->Frows ; + Fcols = Work->Fcols ; + Frpos = Work->Frpos ; + Fcpos = Work->Fcpos ; + fnrows_max = Work->fnrows_max ; + fncols_max = Work->fncols_max ; + fnr_curr = Work->fnr_curr ; + fnc_curr = Work->fnc_curr ; + fnrows = Work->fnrows ; + fncols = Work->fncols ; + fnpiv = Work->fnpiv ; + E = Work->E ; + + DEBUG6 (("=== fnpiv= "ID"\n", fnpiv)) ; + DEBUG6 (("fnrows_max fncols_max "ID" "ID"\n",fnrows_max, fncols_max)) ; + DEBUG6 (("fnr_curr fnc_curr "ID" "ID"\n",fnr_curr, fnc_curr)) ; + DEBUG6 (("fnrows fncols "ID" "ID"\n",fnrows, fncols)) ; + ASSERT ((fnr_curr % 2 == 1) || fnr_curr == 0) ; + DEBUG6 (("Pivot row pattern:\n")) ; + for (j = 0 ; j < fncols ; j++) + { + DEBUG7 ((ID" "ID" "ID" %d\n", j, Fcols [j], Fcpos [Fcols [j]], + j < fncols)) ; + if (check) + { + ASSERT (Fcols [j] >= 0 && Fcols [j] < Work->n_col) ; + ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ; + } + } + DEBUG6 (("Pivot col pattern:\n")) ; + for (i = 0 ; i < fnrows ; i++) + { + DEBUG7 ((ID" "ID" "ID" %d\n", i, Frows [i], Frpos [Frows [i]], + i < fnrows)) ; + if (check) + { + ASSERT (Frows [i] >= 0 && Frows [i] < Work->n_row) ; + ASSERT (Frpos [Frows [i]] == i) ; + } + } + if (UMF_debug < 7) return ; + + if (!E [0]) + { + DEBUG6 (("current front not allocated\n")) ; + ASSERT (!Work->Flublock) ; + return ; + } + + ASSERT (Work->Flublock == (Entry *) (Numeric->Memory + E [0])) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Fcblock, fnr_curr, fnrows, fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Flblock, fnr_curr, fnrows, fnpiv) ; + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Fublock, fnc_curr, fncols, fnpiv) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Flublock, Work->nb, fnpiv, fnpiv) ; + if (fnpiv > 0) + { + DEBUG7 (("Pivot entry: ")) ; + EDEBUG7 (Flublock [(fnpiv-1)+(fnpiv-1)*Work->nb]) ; + DEBUG7 (("\n")) ; + } +} + +/* ========================================================================== */ +/* === UMF_dump_lu ========================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_lu +( + NumericType *Numeric +) +{ + Int i, n_row, n_col, *Cperm, *Rperm ; + + DEBUG6 (("=============================================== LU factors:\n")) ; + if (!Numeric) + { + DEBUG6 (("No LU factors allocated\n")) ; + return ; + } + n_row = Numeric->n_row ; + n_col = Numeric->n_col ; + DEBUG6 (("n_row: "ID" n_col: "ID"\n", n_row, n_col)) ; + DEBUG6 (("nLentries: "ID" nUentries: "ID"\n", + Numeric->nLentries, Numeric->nUentries)) ; + + if (Numeric->Cperm) + { + Cperm = Numeric->Cperm ; + DEBUG7 (("Column permutations: (new: old)\n")) ; + for (i = 0 ; i < n_col ; i++) + { + if (Cperm [i] != EMPTY) + { + DEBUG7 ((ID": "ID"\n", i, Cperm [i])) ; + } + } + } + else + { + DEBUG7 (("No Numeric->Cperm allocatated\n")) ; + } + + if (Numeric->Rperm) + { + Rperm = Numeric->Rperm ; + DEBUG7 (("row permutations: (new: old)\n")) ; + for (i = 0 ; i < n_row ; i++) + { + if (Rperm [i] != EMPTY) + { + DEBUG7 ((ID": "ID"\n", i, Rperm [i])) ; + } + } + } + else + { + DEBUG7 (("No Numeric->Rperm allocatated\n")) ; + } + + DEBUG6 (("========================================= END OF LU factors:\n")); +} + + +/* ========================================================================== */ +/* === UMF_dump_memory ====================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_memory +( + NumericType *Numeric +) +{ + + Unit *p ; + Int prevsize, s ; + Int found ; + + if (!Numeric) + { + DEBUG6 (("No memory space S allocated\n")) ; + return ; + } + + DEBUG6 (("\n ============================================== MEMORY:\n")) ; + if (!Numeric || !Numeric->Memory) + { + DEBUG6 (("No memory space Numeric allocated\n")) ; + return ; + } + + DEBUG6 (("S: "ID"\n", (Int) Numeric)) ; + DEBUG6 (("S->ihead : "ID"\n", Numeric->ihead)) ; + DEBUG6 (("S->itail : "ID"\n", Numeric->itail)) ; + DEBUG6 (("S->size : "ID"\n", Numeric->size)) ; + DEBUG6 (("S->ngarbage : "ID"\n", Numeric->ngarbage)) ; + DEBUG6 (("S->nrealloc : "ID"\n", Numeric->nrealloc)) ; + DEBUG6 ((" in use at head : "ID"\n", Numeric->ihead)) ; + DEBUG6 ((" free space : "ID"\n", + Numeric->itail - Numeric->ihead)) ; + DEBUG6 ((" blocks in use at tail : "ID"\n", + Numeric->size - Numeric->itail)) ; + DEBUG6 ((" total in use : "ID"\n", + Numeric->size - (Numeric->itail - Numeric->ihead))) ; + + prevsize = 0 ; + found = FALSE ; + + ASSERT (0 <= Numeric->ihead) ; + ASSERT (Numeric->ihead <= Numeric->itail) ; + ASSERT (Numeric->itail <= Numeric->size) ; + + p = Numeric->Memory + Numeric->itail ; + + while (p < Numeric->Memory + Numeric->size) + { + DEBUG8 (("p: "ID" p+1: "ID" prevsize: "ID" size: "ID, + (Int) (p-Numeric->Memory), (Int) (p+1-Numeric->Memory), + p->header.prevsize, p->header.size)) ; + if (p->header.size < 0) + { + DEBUG8 ((" free")) ; + } + + if (p == Numeric->Memory + Numeric->itail) + { + ASSERT (p->header.prevsize == 0) ; + } + else + { + ASSERT (p->header.prevsize > 0) ; + } + + ASSERT (p->header.size != 0) ; + s = prevsize >= 0 ? prevsize : -prevsize ; + ASSERT (p->header.prevsize == s) ; + /* no adjacent free blocks */ + ASSERT (p->header.size > 0 || prevsize > 0) ; + if (Numeric->ibig != EMPTY) + { + if (p == Numeric->Memory + Numeric->ibig) + { + ASSERT (p->header.size < 0) ; + DEBUG8 ((" <===== Numeric->ibig")) ; + found = TRUE ; + } + } + s = p->header.size ; + prevsize = s ; + s = s >= 0 ? s : -s ; + p = p + 1 + s ; + DEBUG8 (("\n")) ; + } + + ASSERT (p == Numeric->Memory + Numeric->size) ; + ASSERT (IMPLIES (Numeric->ibig != EMPTY, found)) ; + DEBUG6 (("============================================= END OF MEMORY:\n")); + +} + + +/* ========================================================================== */ +/* === UMF_dump_packed_memory =============================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_packed_memory +( + NumericType *Numeric, + WorkType *Work +) +{ + Unit *p, *p3 ; + Int prevsize, col, row, *Rows, *Cols, ncols, nrows, k, esize, + *Row_tuples, *Row_degree, *Col_tuples, *Col_degree ; + Entry *C ; + Element *ep ; + + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ + Row_tuples = Numeric->Uip ; + Col_tuples = Numeric->Lip ; + + DEBUG6 (("============================================ PACKED MEMORY:\n")) ; + if (!Numeric || !Numeric->Memory) + { + DEBUG6 (("No memory space S allocated\n")) ; + return ; + } + DEBUG6 (("S: "ID"\n", (Int) Numeric)) ; + DEBUG6 (("S->ihead : "ID"\n", Numeric->ihead)) ; + DEBUG6 (("S->itail : "ID"\n", Numeric->itail)) ; + DEBUG6 (("S->size : "ID"\n", Numeric->size)) ; + DEBUG6 (("S->ngarbage : "ID"\n", Numeric->ngarbage)) ; + DEBUG6 (("S->nrealloc : "ID"\n", Numeric->nrealloc)) ; + DEBUG6 ((" in use at head : "ID"\n", Numeric->ihead)) ; + DEBUG6 ((" free space : "ID"\n", + Numeric->itail - Numeric->ihead)) ; + DEBUG6 ((" blocks in use at tail : "ID"\n", + Numeric->size - Numeric->itail)) ; + DEBUG6 ((" total in use : "ID"\n", + Numeric->size - (Numeric->itail - Numeric->ihead))) ; + + ASSERT (0 <= Numeric->ihead) ; + ASSERT (Numeric->ihead <= Numeric->itail) ; + ASSERT (Numeric->itail <= Numeric->size) ; + + for (row = 0 ; row < Work->n_row ; row++) + { + ASSERT (IMPLIES (NON_PIVOTAL_ROW (row), !Row_tuples [row])) ; + } + for (col = 0 ; col < Work->n_col ; col++) + { + ASSERT (IMPLIES (NON_PIVOTAL_COL (col), !Col_tuples [col])) ; + } + + prevsize = 0 ; + p = Numeric->Memory + Numeric->itail ; + while (p < Numeric->Memory + Numeric->size) + { + DEBUG9 (("====================\n")) ; + DEBUG7 (("p: "ID" p+1: "ID" prevsize: "ID" size: "ID"\n", + (Int) (p-Numeric->Memory), (Int) (p+1-Numeric->Memory), + p->header.prevsize, p->header.size)) ; + ASSERT (p->header.size > 0) ; + + if (p == Numeric->Memory + Numeric->itail) + { + ASSERT (p->header.prevsize == 0) ; + } + else + { + ASSERT (p->header.prevsize > 0) ; + } + + ASSERT (p->header.prevsize == prevsize) ; + prevsize = p->header.size ; + + if (p != Numeric->Memory + Numeric->size - 2) + { + + p3 = p + 1 ; + if (p3 == Numeric->Memory + Work->E [0]) + { + /* this is the current frontal matrix */ + UMF_dump_current_front (Numeric, Work, FALSE) ; + } + else + { + + /* this is a packed element */ + GET_ELEMENT (ep, p3, Cols, Rows, ncols, nrows, C) ; + DEBUG9 (("ep "ID"\n nrows "ID" ncols "ID"\n", + (Int) ((p+1)-Numeric->Memory), ep->nrows, ep->ncols)) ; + DEBUG9 (("rows:")) ; + for (k = 0 ; k < ep->nrows; k++) + { + row = Rows [k] ; + DEBUG9 ((" "ID, row)) ; + ASSERT (row >= 0 && row <= Work->n_row) ; + if ((k % 10) == 9) DEBUG9 (("\n")) ; + } + DEBUG9 (("\ncols:")) ; + for (k = 0 ; k < ep->ncols; k++) + { + col = Cols [k] ; + DEBUG9 ((" "ID, col)) ; + ASSERT (col >= 0 && col <= Work->n_col) ; + if ((k % 10) == 9) DEBUG9 (("\n")) ; + } + DEBUG9 (("\nvalues: ")) ; + if (UMF_debug >= 9) + { + UMF_dump_dense (C, ep->nrows, ep->nrows, ep->ncols) ; + } + esize = GET_ELEMENT_SIZE (ep->nrows, ep->ncols) ; + DEBUG9 (("esize: "ID"\n", esize)) ; + ASSERT (esize <= p->header.size) ; + } + + } + else + { + /* this is the final marker block */ + ASSERT (p->header.size == 1) ; + } + p = p + 1 + p->header.size ; + } + + ASSERT (Numeric->ibig == EMPTY) ; + ASSERT (p == Numeric->Memory + Numeric->size) ; + DEBUG6 (("======================================END OF PACKED MEMORY:\n")) ; + +} + +/* ========================================================================== */ +/* === UMF_dump_col_matrix ================================================== */ +/* ========================================================================== */ + +/* This code is the same for real or complex matrices. */ + +GLOBAL void UMF_dump_col_matrix +( + const double Ax [ ], /* Ax [0..nz-1]: real values, in column order */ +#ifdef COMPLEX + const double Az [ ], /* Az [0..nz-1]: imag values, in column order */ +#endif + const Int Ai [ ], /* Ai [0..nz-1]: row indices, in column order */ + const Int Ap [ ], /* Ap [0..n_col]: column pointers */ + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Int nz /* number of entries */ +) +{ + Int col, p, p1, p2, row ; +#ifdef COMPLEX + Int split = SPLIT (Az) ; +#endif + + if (!Ai || !Ap) return ; + DEBUG6 (("============================================ COLUMN FORM:\n")) ; + + ASSERT (n_col >= 0) ; + nz = Ap [n_col] ; + DEBUG2 (("UMF_dump_col: nz "ID"\n", nz)) ; + DEBUG2 (("n_row "ID" \n", n_row)) ; + DEBUG2 (("n_col "ID" \n", n_col)) ; + + DEBUG6 ((" n_row = "ID", n_col ="ID" nz = "ID" Ap [0] "ID", Ap [n] "ID"\n", + n_row, n_col, nz, Ap [0], Ap [n_col])) ; + ASSERT (Ap [0] == 0) ; + ASSERT (Ap [n_col] == nz) ; + for (col = 0 ; col < n_col ; col++) + { + p1 = Ap [col] ; + p2 = Ap [col+1] ; + DEBUG6 (("col: "ID", length "ID"\n", col, p2 - p1)) ; + ASSERT (p2 >= p1) ; + for (p = p1 ; p < p2 ; p++) + { + row = Ai [p] ; + ASSERT (row >= 0 && row < n_row) ; + DEBUG6 (("\t"ID" ", row)) ; + if (Ax != (double *) NULL) + { +#ifdef COMPLEX + if (split) + { + DEBUG6 ((" (%e+%ei) ", Ax [p], Az [p])) ; + } + else + { + DEBUG6 ((" (%e+%ei) ", Ax [2*p], Ax [2*p+1])) ; + } +#else + DEBUG6 ((" %e", Ax [p])) ; +#endif + } + DEBUG6 (("\n")) ; + } + } + DEBUG6 (("========================================== COLUMN FORM done\n")) ; +} + + +/* ========================================================================== */ +/* === UMF_dump_chain ======================================================= */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_chain +( + Int frontid, + Int Front_parent [ ], + Int Front_npivcol [ ], + Int Front_nrows [ ], + Int Front_ncols [ ], + Int nfr +) +{ + Int i, len = 0 ; + + /* print a list of contiguous parents */ + i = frontid ; + ASSERT (Front_parent [i] == EMPTY || + (Front_parent [i] > i && Front_parent [i] < nfr)) ; + + len++ ; + DEBUG3 (("Chain:\n "ID" ["ID","ID"]("ID"-by-"ID")\n", i, + Front_npivcol [i], + MIN (Front_npivcol [i], Front_nrows [i]), + Front_nrows [i], + Front_ncols [i])) ; + + for (i = frontid ; i < nfr ; i++) + { + ASSERT (Front_parent [i] == EMPTY || + (Front_parent [i] > i && Front_parent [i] < nfr)) ; + if (Front_parent [i] == i+1) + { + len++ ; + DEBUG3 (("\t"ID" ["ID","ID"]("ID"-by-"ID")\n", i+1, + Front_npivcol [i+1], + MIN (Front_npivcol [i+1], Front_nrows [i+1]), + Front_nrows [i+1], + Front_ncols [i+1])) ; + } + else + { + DEBUG2 (("Length of chain: "ID"\n", len)) ; + return ; + } + } +} + + +/* ========================================================================== */ +/* === UMF_dump_start ======================================================= */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_start +( + void +) +{ + FILE *ff ; + + AMD_debug_init ("from umfpack") ; + + /* get the debug print level from the "debug.umf" file, if it exists */ + UMF_debug = -999 ; + ff = fopen ("debug.umf", "r") ; + if (ff) + { + (void) fscanf (ff, ID, &UMF_debug) ; + (void) fclose (ff) ; + } + + DEBUG0 (("umfpack: debug version (SLOW!) ")) ; + + DEBUG0 ((" BLAS: ")) ; + +#if defined (USE_NO_BLAS) + DEBUG0 (("none.")) ; +#elif defined (USE_C_BLAS) + DEBUG0 (("C-BLAS.")) ; +#elif defined (USE_MATLAB_BLAS) + DEBUG0 (("built-in MATLAB BLAS.")) ; +#elif defined (USE_SUNPERF_BLAS) + DEBUG0 (("Sun Performance Library BLAS.")) ; +#elif defined (USE_SCSL_BLAS) + DEBUG0 (("SGI SCSL BLAS.")) ; +#elif defined (USE_FORTRAN_BLAS) + DEBUG0 (("Fortran BLAS.")) ; +#endif + + DEBUG0 ((" MATLAB: ")) ; +#ifdef MATLAB_MEX_FILE + DEBUG0 (("mexFunction.\n")) ; +#else +#ifdef MATHWORKS + DEBUG0 (("yes (uses MathWorks internal ut* routines).\n")) ; +#else + DEBUG0 (("no.\n")) ; +#endif +#endif + + UMF_gprob = -1.0 ; + ff = fopen ("gprob.umf", "r") ; + if (ff) + { + (void) fscanf (ff, "%lg", &UMF_gprob) ; + (void) fclose (ff) ; + srand (1) ; /* restart the random number generator */ + } + + if (UMF_gprob > 1.0) UMF_gprob = 1.0 ; + DEBUG1 (("factor: UMF_gprob: %e UMF_debug "ID"\n", UMF_gprob, UMF_debug)) ; + + DEBUG2 (("sizeof: (bytes / int / Units) \n")) ; + DEBUG2 (("sizeof (Int) %u %u %u\n", + sizeof (Int), sizeof (Int) / sizeof (int), UNITS (Int, 1) )) ; + DEBUG2 (("sizeof (int) %u %u %u\n", + sizeof (int), sizeof (int) / sizeof (int), UNITS (int, 1) )) ; + DEBUG2 (("sizeof (size_t) %u %u %u\n", + sizeof (size_t), sizeof (size_t) / sizeof (size_t), UNITS (size_t, 1) )) ; + DEBUG2 (("sizeof (long) %u %u %u\n", + sizeof (long), sizeof (long) / sizeof (long), UNITS (long, 1) )) ; + DEBUG2 (("sizeof (double) %u %u %u\n", + sizeof (double), sizeof (double) / sizeof (int), UNITS (double, 1) )) ; + DEBUG2 (("sizeof (Unit) %u %u %u\n", + sizeof (Unit), sizeof (Unit) / sizeof (int), UNITS (Unit, 1) )) ; + DEBUG2 (("sizeof (Entry) %u %u %u\n", + sizeof (Entry), sizeof (Entry) / sizeof (int), UNITS (Entry, 1) )) ; + DEBUG2 (("sizeof (Tuple) %u %u %u\n", + sizeof (Tuple), sizeof (Tuple) / sizeof (int), UNITS (Tuple, 1) )) ; + DEBUG2 (("sizeof (Tuple *) %u %u %u\n", + sizeof (Tuple *), sizeof (Tuple *) / sizeof (int), UNITS (Tuple *, 1) )) ; + DEBUG2 (("sizeof (Element) %u %u %u\n", + sizeof (Element), sizeof (Element) / sizeof (int), UNITS (Element, 1) )) ; + DEBUG2 (("sizeof (Element *) %u %u %u\n", + sizeof (Element *), sizeof (Element *) / sizeof (int), + UNITS (Element *, 1) )) ; + DEBUG2 (("sizeof (WorkType) %u %u %u\n", + sizeof (WorkType), sizeof (WorkType) / sizeof (int), + UNITS (WorkType, 1) )) ; + DEBUG2 (("sizeof (NumericType) %u %u %u\n", + sizeof (NumericType), sizeof (NumericType) / sizeof (int), + UNITS (NumericType, 1) )) ; + DEBUG2 (("sizeof (SymbolicType) %u %u %u\n", + sizeof (SymbolicType), sizeof (SymbolicType) / sizeof (int), + UNITS (SymbolicType, 1) )) ; + +} + + +/* ========================================================================== */ +/* === UMF_dump_rowmerge ==================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_rowmerge +( + NumericType *Numeric, + SymbolicType *Symbolic, + WorkType *Work +) +{ + Int *Front_leftmostdesc, *Front_1strow, *Front_new1strow, row1, row2, + fleftmost, nfr, n_row, *Row_degree, i, frontid, row ; + + nfr = Symbolic->nfr ; + DEBUG3 (("\n================== Row merge sets: nfr "ID"\n", nfr)) ; + Front_leftmostdesc = Symbolic->Front_leftmostdesc ; + Front_1strow = Symbolic->Front_1strow ; + Front_new1strow = Work->Front_new1strow ; + n_row = Symbolic->n_row ; + Row_degree = Numeric->Rperm ; + frontid = Work->frontid ; + + for (i = frontid ; i <= nfr ; i++) + { + DEBUG3 (("----------------------\n")) ; + if (i == nfr) DEBUG3 (("Dummy: ")) ; + DEBUG3 (("Front "ID" 1strow "ID" new1strow "ID" leftmostdesc "ID, + i, Front_1strow [i], Front_new1strow [i], Front_leftmostdesc [i])) ; + DEBUG3 ((" parent "ID" pivcol "ID"\n", Symbolic->Front_parent [i], + Symbolic->Front_npivcol [i])) ; + + if (i == nfr) + { + fleftmost = -1 ; + row1 = Front_new1strow [i] ; + row2 = n_row-1 ; + } + else + { + fleftmost = Front_leftmostdesc [i] ; + row1 = Front_new1strow [fleftmost] ; + row2 = Front_1strow [i+1] - 1 ; + } + DEBUG3 (("Leftmost: "ID" Rows ["ID" to "ID"], search ["ID" to "ID"]\n", + fleftmost, Front_1strow [i], row2, row1, row2)) ; + + for (row = row1 ; row <= row2 ; row++) + { + ASSERT (row >= 0 && row < n_row) ; + DEBUG3 ((" Row "ID" live: %d\n", row, NON_PIVOTAL_ROW (row))) ; + } + } +} + +/* ========================================================================== */ +/* === UMF_dump_diagonal_map ================================================ */ +/* ========================================================================== */ + +GLOBAL void UMF_dump_diagonal_map +( + Int Diagonal_map [ ], + Int Diagonal_imap [ ], + Int n1, + Int nn, + Int nempty +) +{ + Int row, col ; + if (Diagonal_map != (Int *) NULL) + { + DEBUG2 (("\nDump the Diagonal_map: n1 "ID" nn "ID" nempty "ID"\n", + n1, nn, nempty)) ; + for (col = n1 ; col < nn - nempty ; col++) + { + row = Diagonal_map [col] ; + DEBUG2 ((" Diagonal_map [col = "ID"] gives "ID": ", + col, row)) ; + row = UNFLIP (row) ; + DEBUG2 ((" row "ID"\n", row)) ; + ASSERT (Diagonal_imap [row] == col) ; + } + } +} + +#endif /* NDEBUG */ diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_dump.h b/liboctave/UMFPACK/UMFPACK/Source/umf_dump.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_dump.h @@ -0,0 +1,186 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* umf_dump.h: debugging definitions. */ + +#ifndef NDEBUG + +GLOBAL void UMF_dump_dense +( + Entry *C, + Int dim, + Int m, + Int n +) ; + +GLOBAL void UMF_dump_element +( + NumericType *Numeric, + WorkType *Work, + Int e, + Int clean +) ; + +GLOBAL void UMF_dump_rowcol +( + Int dump_which, + NumericType *Numeric, + WorkType *Work, + Int dump_index, + Int check_degree +) ; + +GLOBAL void UMF_dump_matrix +( + NumericType *Numeric, + WorkType *Work, + Int check_degree +) ; + +GLOBAL void UMF_dump_current_front +( + NumericType *Numeric, + WorkType *Work, + Int check +) ; + +GLOBAL void UMF_dump_lu +( + NumericType *Numeric +) ; + +GLOBAL void UMF_dump_memory +( + NumericType *Numeric +) ; + +GLOBAL void UMF_dump_packed_memory +( + NumericType *Numeric, + WorkType *Work +) ; + +GLOBAL void UMF_dump_col_matrix +( + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + const Int Ai [ ], + const Int Ap [ ], + Int n_row, + Int n_col, + Int nz +) ; + +GLOBAL void UMF_dump_chain +( + Int frontid, + Int Front_parent [ ], + Int Front_npivcol [ ], + Int Front_nrows [ ], + Int Front_ncols [ ], + Int nfr +) ; + +GLOBAL void UMF_dump_rowmerge +( + NumericType *Numeric, + SymbolicType *Symbolic, + WorkType *Work +) ; + +GLOBAL void UMF_dump_start +( + void +) ; + + +GLOBAL void UMF_dump_diagonal_map +( + Int Diagonal_map [ ], + Int Diagonal_imap [ ], + Int n1, + Int nn, + Int nempty +) ; + +#define UMF_DBMAX 50000 +GLOBAL extern Int UMF_debug ; +GLOBAL extern Int UMF_allocfail ; +GLOBAL extern double UMF_gprob ; + +#define DEBUGk(k,params) { if (UMF_debug >= (k)) { PRINTF (params) ; } } + +#define DEBUGm4(params) DEBUGk (-4, params) +#define DEBUGm3(params) DEBUGk (-3, params) +#define DEBUGm2(params) DEBUGk (-2, params) +#define DEBUGm1(params) DEBUGk (-1, params) +#define DEBUG0(params) DEBUGk (0, params) +#define DEBUG1(params) DEBUGk (1, params) +#define DEBUG2(params) DEBUGk (2, params) +#define DEBUG3(params) DEBUGk (3, params) +#define DEBUG4(params) DEBUGk (4, params) +#define DEBUG5(params) DEBUGk (5, params) +#define DEBUG6(params) DEBUGk (6, params) +#define DEBUG7(params) DEBUGk (7, params) +#define DEBUG8(params) DEBUGk (8, params) +#define DEBUG9(params) DEBUGk (9, params) + +#define EDEBUGk(k,a) { if (UMF_debug >= (k)) { PRINT_ENTRY (a) ; } } + +#define EDEBUG0(a) EDEBUGk (0, a) +#define EDEBUG1(a) EDEBUGk (1, a) +#define EDEBUG2(a) EDEBUGk (2, a) +#define EDEBUG3(a) EDEBUGk (3, a) +#define EDEBUG4(a) EDEBUGk (4, a) +#define EDEBUG5(a) EDEBUGk (5, a) +#define EDEBUG6(a) EDEBUGk (6, a) +#define EDEBUG7(a) EDEBUGk (7, a) +#define EDEBUG8(a) EDEBUGk (8, a) +#define EDEBUG9(a) EDEBUGk (9, a) + +/* ASSERT defined in amd_dump.h */ + +#else + +/* ========================================================================== */ +/* === No debugging ========================================================= */ +/* ========================================================================== */ + +/* turn off all debugging macros */ + +#define DEBUGk(k,params) + +#define DEBUGm4(params) +#define DEBUGm3(params) +#define DEBUGm2(params) +#define DEBUGm1(params) +#define DEBUG0(params) +#define DEBUG1(params) +#define DEBUG2(params) +#define DEBUG3(params) +#define DEBUG4(params) +#define DEBUG5(params) +#define DEBUG6(params) +#define DEBUG7(params) +#define DEBUG8(params) +#define DEBUG9(params) + +#define EDEBUGk(k,a) + +#define EDEBUG0(a) +#define EDEBUG1(a) +#define EDEBUG2(a) +#define EDEBUG3(a) +#define EDEBUG4(a) +#define EDEBUG5(a) +#define EDEBUG6(a) +#define EDEBUG7(a) +#define EDEBUG8(a) +#define EDEBUG9(a) + +#endif /* NDEBUG */ diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.c b/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.c @@ -0,0 +1,392 @@ +/* ========================================================================== */ +/* === UMF_extend_front ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Called by kernel. */ + +#include "umf_internal.h" +#include "umf_grow_front.h" + +/* ========================================================================== */ +/* === zero_front =========================================================== */ +/* ========================================================================== */ + +PRIVATE void zero_front ( + Entry *Flblock, Entry *Fublock, Entry *Fcblock, + Int fnrows, Int fncols, Int fnr_curr, Int fnc_curr, + Int fnpiv, Int fnrows_extended, Int fncols_extended) +{ + Int j, i ; + Entry *F, *Fj, *Fi ; + + Fj = Fcblock + fnrows ; + for (j = 0 ; j < fncols ; j++) + { + /* zero the new rows in the contribution block: */ + F = Fj ; + Fj += fnr_curr ; +#pragma ivdep + for (i = fnrows ; i < fnrows_extended ; i++) + { + /* CLEAR (Fcblock [i + j*fnr_curr]) ; */ + CLEAR_AND_INCREMENT (F) ; + } + } + + Fj -= fnrows ; + for (j = fncols ; j < fncols_extended ; j++) + { + /* zero the new columns in the contribution block: */ + F = Fj ; + Fj += fnr_curr ; +#pragma ivdep + for (i = 0 ; i < fnrows_extended ; i++) + { + /* CLEAR (Fcblock [i + j*fnr_curr]) ; */ + CLEAR_AND_INCREMENT (F) ; + } + } + + Fj = Flblock + fnrows ; + for (j = 0 ; j < fnpiv ; j++) + { + /* zero the new rows in L block: */ + F = Fj ; + Fj += fnr_curr ; +#pragma ivdep + for (i = fnrows ; i < fnrows_extended ; i++) + { + /* CLEAR (Flblock [i + j*fnr_curr]) ; */ + CLEAR_AND_INCREMENT (F) ; + } + } + + Fi = Fublock + fncols ; + for (i = 0 ; i < fnpiv ; i++) + { + /* zero the new columns in U block: */ + F = Fi ; + Fi += fnc_curr ; +#pragma ivdep + for (j = fncols ; j < fncols_extended ; j++) + { + /* CLEAR (Fublock [i*fnc_curr + j]) ; */ + CLEAR_AND_INCREMENT (F) ; + } + } + +} + +/* ========================================================================== */ +/* === UMF_extend_front ===================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMF_extend_front +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int j, i, *Frows, row, col, *Wrow, fnr2, fnc2, *Frpos, *Fcpos, *Fcols, + fnrows_extended, rrdeg, ccdeg, fncols_extended, fnr_curr, fnc_curr, + fnrows, fncols, pos, fnpiv, *Wm ; + Entry *Wx, *Wy, *Fu, *Fl ; + + /* ---------------------------------------------------------------------- */ + /* get current frontal matrix and check for frontal growth */ + /* ---------------------------------------------------------------------- */ + + fnpiv = Work->fnpiv ; + +#ifndef NDEBUG + DEBUG2 (("EXTEND FRONT\n")) ; + DEBUG2 (("Work->fnpiv "ID"\n", fnpiv)) ; + ASSERT (Work->Flblock == Work->Flublock + Work->nb*Work->nb) ; + ASSERT (Work->Fublock == Work->Flblock + Work->fnr_curr*Work->nb) ; + ASSERT (Work->Fcblock == Work->Fublock + Work->nb*Work->fnc_curr) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Work->Fcblock, Work->fnr_curr, Work->fnrows, Work->fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Work->Flblock, Work->fnr_curr, Work->fnrows, fnpiv); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Work->Fublock, Work->fnc_curr, Work->fncols, fnpiv) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Work->Flublock, Work->nb, fnpiv, fnpiv) ; +#endif + + if (Work->do_grow) + { + fnr2 = UMF_FRONTAL_GROWTH * Work->fnrows_new + 2 ; + fnc2 = UMF_FRONTAL_GROWTH * Work->fncols_new + 2 ; + if (!UMF_grow_front (Numeric, fnr2, fnc2, Work, 1)) + { + DEBUGm4 (("out of memory: extend front\n")) ; + return (FALSE) ; + } + } + + fnr_curr = Work->fnr_curr ; + fnc_curr = Work->fnc_curr ; + ASSERT (Work->fnrows_new + 1 <= fnr_curr) ; + ASSERT (Work->fncols_new + 1 <= fnc_curr) ; + ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + Frows = Work->Frows ; + Frpos = Work->Frpos ; + Fcols = Work->Fcols ; + Fcpos = Work->Fcpos ; + fnrows = Work->fnrows ; + fncols = Work->fncols ; + rrdeg = Work->rrdeg ; + ccdeg = Work->ccdeg ; + + /* scan starts at the first new column in Fcols */ + /* also scan the pivot column if it was not in the front */ + Work->fscan_col = fncols ; + Work->NewCols = Fcols ; + + /* scan1 starts at the first new row in Frows */ + /* also scan the pivot row if it was not in the front */ + Work->fscan_row = fnrows ; + Work->NewRows = Frows ; + + /* ---------------------------------------------------------------------- */ + /* extend row pattern of the front with the new pivot column */ + /* ---------------------------------------------------------------------- */ + + fnrows_extended = fnrows ; + fncols_extended = fncols ; + +#ifndef NDEBUG + DEBUG2 (("Pivot col, before extension: "ID"\n", fnrows)) ; + for (i = 0 ; i < fnrows ; i++) + { + DEBUG2 ((" "ID": row "ID"\n", i, Frows [i])) ; + ASSERT (Frpos [Frows [i]] == i) ; + } + DEBUG2 (("Extending pivot column: pivcol_in_front: "ID"\n", + Work->pivcol_in_front)) ; +#endif + + Fl = Work->Flblock + fnpiv * fnr_curr ; + + if (Work->pivcol_in_front) + { + /* extended pattern and position already in Frows, Frpos. Values above + * the diagonal are already in LU block. Values on and below the + * diagonal are in Wy [0 .. fnrows_extended-1]. Copy into the L + * block. */ + fnrows_extended += ccdeg ; + Wy = Work->Wy ; + + for (i = 0 ; i < fnrows_extended ; i++) + { + Fl [i] = Wy [i] ; +#ifndef NDEBUG + row = Frows [i] ; + DEBUG2 ((" "ID": row "ID" ", i, row)) ; + EDEBUG2 (Fl [i]) ; + if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ; + DEBUG2 (("\n")) ; + if (i == fnrows - 1) DEBUG2 ((" :::::::\n")) ; + ASSERT (row >= 0 && row < Work->n_row) ; + ASSERT (Frpos [row] == i) ; +#endif + } + + } + else + { + /* extended pattern,values is in (Wm,Wx), not yet in the front */ + Entry *F ; + Fu = Work->Flublock + fnpiv * Work->nb ; + Wm = Work->Wm ; + Wx = Work->Wx ; + F = Fu ; + for (i = 0 ; i < fnpiv ; i++) + { + CLEAR_AND_INCREMENT (F) ; + } + F = Fl ; + for (i = 0 ; i < fnrows ; i++) + { + CLEAR_AND_INCREMENT (F) ; + } + for (i = 0 ; i < ccdeg ; i++) + { + row = Wm [i] ; +#ifndef NDEBUG + DEBUG2 ((" "ID": row "ID" (ext) ", fnrows_extended, row)) ; + EDEBUG2 (Wx [i]) ; + if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ; + DEBUG2 (("\n")) ; + ASSERT (row >= 0 && row < Work->n_row) ; +#endif + pos = Frpos [row] ; + if (pos < 0) + { + pos = fnrows_extended++ ; + Frows [pos] = row ; + Frpos [row] = pos ; + } + Fl [pos] = Wx [i] ; + } + } + + ASSERT (fnrows_extended <= fnr_curr) ; + + /* ---------------------------------------------------------------------- */ + /* extend the column pattern of the front with the new pivot row */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG6 (("Pivot row, before extension: "ID"\n", fncols)) ; + for (j = 0 ; j < fncols ; j++) + { + DEBUG7 ((" "ID": col "ID"\n", j, Fcols [j])) ; + ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ; + } + DEBUG6 (("Extending pivot row:\n")) ; +#endif + + if (Work->pivrow_in_front) + { + if (Work->pivcol_in_front) + { + ASSERT (Fcols == Work->Wrow) ; + for (j = fncols ; j < rrdeg ; j++) + { +#ifndef NDEBUG + col = Fcols [j] ; + DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ; + ASSERT (col != Work->pivcol) ; + ASSERT (col >= 0 && col < Work->n_col) ; + ASSERT (Fcpos [col] < 0) ; +#endif + Fcpos [Fcols [j]] = j * fnr_curr ; + } + } + else + { + /* OUT-IN option: pivcol not in front, but pivrow is in front */ + Wrow = Work->Wrow ; + ASSERT (IMPLIES (Work->pivcol_in_front, Wrow == Fcols)) ; + if (Wrow == Fcols) + { + /* Wrow and Fcols are equivalenced */ + for (j = fncols ; j < rrdeg ; j++) + { + col = Wrow [j] ; + DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ; + ASSERT (Fcpos [col] < 0) ; + /* Fcols [j] = col ; not needed */ + Fcpos [col] = j * fnr_curr ; + } + } + else + { + for (j = fncols ; j < rrdeg ; j++) + { + col = Wrow [j] ; + DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ; + ASSERT (Fcpos [col] < 0) ; + Fcols [j] = col ; + Fcpos [col] = j * fnr_curr ; + } + } + } + fncols_extended = rrdeg ; + } + else + { + ASSERT (Fcols != Work->Wrow) ; + Wrow = Work->Wrow ; + for (j = 0 ; j < rrdeg ; j++) + { + col = Wrow [j] ; + ASSERT (col >= 0 && col < Work->n_col) ; + if (Fcpos [col] < 0) + { + DEBUG2 ((" col:: "ID" (ext)\n", col)) ; + Fcols [fncols_extended] = col ; + Fcpos [col] = fncols_extended * fnr_curr ; + fncols_extended++ ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* pivot row and column have been extended */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + ASSERT (fncols_extended <= fnc_curr) ; + ASSERT (fnrows_extended <= fnr_curr) ; + + DEBUG6 (("Pivot col, after ext: "ID" "ID"\n", fnrows,fnrows_extended)) ; + for (i = 0 ; i < fnrows_extended ; i++) + { + row = Frows [i] ; + DEBUG7 ((" "ID": row "ID" pos "ID" old: %d", i, row, Frpos [row], + i < fnrows)) ; + if (row == Work->pivrow ) DEBUG7 ((" <-- pivrow")) ; + DEBUG7 (("\n")) ; + ASSERT (Frpos [Frows [i]] == i) ; + } + + DEBUG6 (("Pivot row position: "ID"\n", Frpos [Work->pivrow])) ; + ASSERT (Frpos [Work->pivrow] >= 0) ; + ASSERT (Frpos [Work->pivrow] < fnrows_extended) ; + + DEBUG6 (("Pivot row, after ext: "ID" "ID"\n", fncols,fncols_extended)) ; + for (j = 0 ; j < fncols_extended ; j++) + { + col = Fcols [j] ; + DEBUG7 ((" "ID": col "ID" pos "ID" old: %d", j, col, Fcpos [col], + j < fncols)) ; + if (col == Work->pivcol ) DEBUG7 ((" <-- pivcol")) ; + DEBUG7 (("\n")) ; + ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ; + } + + DEBUG6 (("Pivot col position: "ID"\n", Fcpos [Work->pivcol])) ; + ASSERT (Fcpos [Work->pivcol] >= 0) ; + ASSERT (Fcpos [Work->pivcol] < fncols_extended * fnr_curr) ; + +#endif + + /* ---------------------------------------------------------------------- */ + /* Zero the newly extended frontal matrix */ + /* ---------------------------------------------------------------------- */ + + zero_front (Work->Flblock, Work->Fublock, Work->Fcblock, + fnrows, fncols, fnr_curr, fnc_curr, + fnpiv, fnrows_extended, fncols_extended) ; + + /* ---------------------------------------------------------------------- */ + /* finalize extended row and column pattern of the frontal matrix */ + /* ---------------------------------------------------------------------- */ + + Work->fnrows = fnrows_extended ; + Work->fncols = fncols_extended ; + + ASSERT (fnrows_extended == Work->fnrows_new + 1) ; + ASSERT (fncols_extended == Work->fncols_new + 1) ; + + return (TRUE) ; + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.h b/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_extend_front.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_extend_front +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_free.c b/liboctave/UMFPACK/UMFPACK/Source/umf_free.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_free.c @@ -0,0 +1,45 @@ +/* ========================================================================== */ +/* === UMF_free ============================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Free a block previously allocated by UMF_malloc and return NULL. + Usage is p = UMF_free (p), to ensure that we don't free it twice. + Also maintains the UMFPACK malloc count. +*/ + +#include "umf_internal.h" + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) +#include "umf_malloc.h" +#endif + +GLOBAL void *UMF_free +( + void *p +) +{ + DEBUG0 (("UMF_free: "ID"\n", (Int) p)) ; + if (p) + { + + /* see umf_config.h for the memory allocator selection */ + FREE (p) ; + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) + /* One more object has been free'd. Keep track of the count. */ + /* (purely for sanity checks). */ + UMF_malloc_count-- ; + DEBUG0 ((" new malloc count: "ID"\n", UMF_malloc_count)) ; +#endif + + } + + return ((void *) NULL) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_free.h b/liboctave/UMFPACK/UMFPACK/Source/umf_free.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_free.h @@ -0,0 +1,10 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void *UMF_free +( + void *p +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.c b/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.c @@ -0,0 +1,69 @@ +/* ========================================================================== */ +/* === UMF_fsize ============================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Determine the largest frontal matrix size for each subtree. Called by + * UMF_colamd and UMF_analyze. Only required to sort the children of each + * node prior to AMD_postorder. */ + +#include "umf_internal.h" + +GLOBAL void UMF_fsize +( + Int nn, + Int Fsize [ ], + Int Fnrows [ ], + Int Fncols [ ], + Int Parent [ ], + Int Npiv [ ] +) +{ + Int j, parent, frsize, r, c ; + + for (j = 0 ; j < nn ; j++) + { + Fsize [j] = EMPTY ; + } + + /* ---------------------------------------------------------------------- */ + /* find max front size for tree rooted at node j, for each front j */ + /* ---------------------------------------------------------------------- */ + + DEBUG1 (("\n\n========================================FRONTS:\n")) ; + for (j = 0 ; j < nn ; j++) + { + if (Npiv [j] > 0) + { + /* this is a frontal matrix */ + parent = Parent [j] ; + r = Fnrows [j] ; + c = Fncols [j] ; + frsize = r * c ; + /* avoid integer overflow */ + if (INT_OVERFLOW (((double) r) * ((double) c))) + { + /* :: frsize int overflow :: */ + frsize = Int_MAX ; + } + DEBUG1 ((""ID" : npiv "ID" size "ID" parent "ID" ", + j, Npiv [j], frsize, parent)) ; + Fsize [j] = MAX (Fsize [j], frsize) ; + DEBUG1 (("Fsize [j = "ID"] = "ID"\n", j, Fsize [j])) ; + if (parent != EMPTY) + { + /* find the maximum frontsize of self and children */ + ASSERT (Npiv [parent] > 0) ; + ASSERT (parent > j) ; + Fsize [parent] = MAX (Fsize [parent], Fsize [j]) ; + DEBUG1 (("Fsize [parent = "ID"] = "ID"\n", + parent, Fsize [parent])); + } + } + } +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.h b/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_fsize.h @@ -0,0 +1,15 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_fsize +( + Int nn, + Int MaxFsize [ ], + Int Fnrows [ ], + Int Fncols [ ], + Int Parent [ ], + Int Npiv [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.c b/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.c @@ -0,0 +1,695 @@ +/* ========================================================================== */ +/* === UMF_garbage_collection =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Compress the elements at the tail of Numeric->Memory, and delete the tuples. + Elements are renumbered. The new numbering space is compressed, and + in the order of element creation (original elements of A first, followed + by the new elements in the order that they were formed). + + Only called by UMF_get_memory. + + There are 5 ways in which garbage collection can be performed: + + Allocate a new working array for the current frontal matrix. In this + case, there are never any pivot rows/columns in the current frontal + matrix (fnpiv = 0), and the old working array for the current frontal + matrix can always be fully compacted, to fnrows-by-fncols. + + UMF_kernel : UMF_extend : UMF_grow_front : UMF_get_memory + UMF_kernel : UMF_init_front : UMF_grow_front : UMF_get_memory + UMF_kernel : UMF_start_front : UMF_grow_front : UMF_get_memory + + Allocate a new element. In this case, UMF_grow_front may or may not + be subsequently called, depending on Work->do_grow. There are never + any pivot rows/columns in the current frontal matrix (fnpiv=0), but one + may be added if UMF_init_front is to be called just after + UMF_create_element. If do_grow is true, then the current front can be + fully compacted, to fnrows-by-fncols. Otherwise, it can only be + partially compacted, to MAX (fnrows, fnrows_new + 1) -by- + MAX (fncols, fncols_new + 1). + + UMF_kernel : UMF_create_element : UMF_get_memory + + Allocate rows of L and columns of U. In this case, the current + frontal matrix is only partially compacted, to (fnrows_new + 1)-by- + (fncols_new + 1). There are pivots in the frontal matrix (fnpiv > 0). + + UMF_kernel : UMF_store_lu : UMF_get_memory +*/ + +#include "umf_internal.h" + +GLOBAL void UMF_garbage_collection +( + NumericType *Numeric, + WorkType *Work, + Int drnew, /* compact current front to drnew-by-dcnew */ + Int dcnew, + Int do_Fcpos +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int size, e, n_row, n_col, nrows, ncols, nrowsleft, ncolsleft, prevsize, + csize, size2, i2, j2, i, j, cdeg, rdeg, *E, row, col, + *Rows, *Cols, *Rows2, *Cols2, nel, e2, *Row_tuples, *Col_tuples, + *Row_degree, *Col_degree ; + Entry *C, *C1, *C3, *C2 ; + Unit *psrc, *pdest, *p, *pnext ; + Element *epsrc, *epdest ; + +#ifndef NDEBUG + Int nmark ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ + Row_tuples = Numeric->Uip ; + Col_tuples = Numeric->Lip ; + E = Work->E ; + n_row = Work->n_row ; + n_col = Work->n_col ; + + /* note that the tuple lengths (Col_tlen and Row_tlen) are updated, but */ + /* the tuple lists themselves are stale and are about to be destroyed */ + /* and recreated. Do not attempt to scan them until they are recreated. */ + +#ifndef NDEBUG + DEBUGm1 (("::::GARBAGE COLLECTION::::\n")) ; + UMF_dump_memory (Numeric) ; +#endif + + Numeric->ngarbage++ ; + + /* ---------------------------------------------------------------------- */ + /* delete the tuple lists by marking the blocks as free */ + /* ---------------------------------------------------------------------- */ + + /* do not modify Row_tlen and Col_tlen */ + /* those are needed for UMF_build_tuples */ + + for (row = 0 ; row < n_row ; row++) + { + if (NON_PIVOTAL_ROW (row) && Row_tuples [row]) + { + DEBUG2 (("row "ID" tuples "ID"\n", row, Row_tuples [row])) ; + p = Numeric->Memory + Row_tuples [row] - 1 ; + DEBUG2 (("Freeing tuple list row "ID", p-S "ID", size "ID"\n", + row, (Int) (p-Numeric->Memory), p->header.size)) ; + ASSERT (p->header.size > 0) ; + ASSERT (p >= Numeric->Memory + Numeric->itail) ; + ASSERT (p < Numeric->Memory + Numeric->size) ; + p->header.size = -p->header.size ; + Row_tuples [row] = 0 ; + } + } + + for (col = 0 ; col < n_col ; col++) + { + if (NON_PIVOTAL_COL (col) && Col_tuples [col]) + { + DEBUG2 (("col "ID" tuples "ID"\n", col, Col_tuples [col])) ; + p = Numeric->Memory + Col_tuples [col] - 1 ; + DEBUG2 (("Freeing tuple list col "ID", p-S "ID", size "ID"\n", + col, (Int) (p-Numeric->Memory), p->header.size)) ; + ASSERT (p->header.size > 0) ; + ASSERT (p >= Numeric->Memory + Numeric->itail) ; + ASSERT (p < Numeric->Memory + Numeric->size) ; + p->header.size = -p->header.size ; + Col_tuples [col] = 0 ; + } + } + + /* ---------------------------------------------------------------------- */ + /* mark the elements, and compress the name space */ + /* ---------------------------------------------------------------------- */ + + nel = Work->nel ; + ASSERT (nel < Work->elen) ; + +#ifndef NDEBUG + nmark = 0 ; + UMF_dump_current_front (Numeric, Work, FALSE) ; + DEBUGm1 (("E [0] "ID" \n", E [0])) ; + ASSERT (IMPLIES (E [0], + Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ; + ASSERT (IMPLIES (Work->Flublock, + Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ; + ASSERT ((E [0] != 0) == (Work->Flublock != (Entry *) NULL)) ; +#endif + + e2 = 0 ; + + for (e = 0 ; e <= nel ; e++) /* for all elements in order of creation */ + { + if (E [e]) + { + psrc = Numeric->Memory + E [e] ; + psrc-- ; /* get the header of this block */ + if (e > 0) + { + e2++ ; /* do not renumber element zero */ + } + ASSERT (psrc->header.size > 0) ; + psrc->header.size = e2 ; /* store the new name in the header */ +#ifndef NDEBUG + nmark++ ; +#endif + DEBUG7 ((ID":: Mark e "ID" at psrc-S "ID", new e "ID"\n", + nmark, e, (Int) (psrc-Numeric->Memory), e2)) ; + E [e] = 0 ; + if (e == Work->prior_element) + { + Work->prior_element = e2 ; + } + } + } + + /* all 1..e2 are now in use (element zero may or may not be in use) */ + Work->nel = e2 ; + nel = Work->nel ; + +#ifndef NDEBUG + for (e = 0 ; e < Work->elen ; e++) + { + ASSERT (!E [e]) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* compress the elements */ + /* ---------------------------------------------------------------------- */ + + /* point to tail marker block of size 1 + header */ + psrc = Numeric->Memory + Numeric->size - 2 ; + pdest = psrc ; + prevsize = psrc->header.prevsize ; + DEBUG7 (("Starting the compression:\n")) ; + + while (prevsize > 0) + { + + /* ------------------------------------------------------------------ */ + /* move up to the next element above the current header, and */ + /* get the element name and size */ + /* (if it is an element, the name will be positive) */ + /* ------------------------------------------------------------------ */ + + size = prevsize ; + psrc -= (size + 1) ; + e = psrc->header.size ; + prevsize = psrc->header.prevsize ; + /* top block at tail has prevsize of 0 */ + + /* a free block will have a negative size, so skip it */ + /* otherwise, if size >= 0, it holds the element name, not the size */ + + DEBUG8 (("psrc-S: "ID" prevsize: "ID" size: "ID, + (Int) (psrc-Numeric->Memory), prevsize, size)) ; + + if (e == 0) + { + /* -------------------------------------------------------------- */ + /* this is the current frontal matrix */ + /* -------------------------------------------------------------- */ + + Entry *F1, *F2, *Fsrc, *Fdst ; + Int c, r, k, dr, dc, gap, gap1, gap2, nb ; + + /* shift the frontal matrix down */ + F1 = (Entry *) (psrc + 1) ; + + /* get the size of the current front. r and c could be zero */ + k = Work->fnpiv ; + dr = Work->fnr_curr ; + dc = Work->fnc_curr ; + r = Work->fnrows ; + c = Work->fncols ; + nb = Work->nb ; + + ASSERT ((dr >= 0 && (dr % 2) == 1) || dr == 0) ; + ASSERT (drnew >= 0) ; + if (drnew % 2 == 0) + { + /* make sure leading frontal matrix dimension is always odd */ + drnew++ ; + } + drnew = MIN (dr, drnew) ; + ASSERT ((drnew >= 0 && (drnew % 2) == 1) || drnew == 0) ; + + pnext = pdest ; + +#ifndef NDEBUG + DEBUGm2 (("move front: dr "ID" dc "ID" r "ID" drnew "ID" c "ID + " dcnew " ID" k "ID"\n", dr, dc, r, drnew, c, dcnew, k)) ; + DEBUG7 (("\n")) ; + DEBUG7 ((ID":: Move current frontal matrix from: psrc-S: "ID" \n", + nmark, (Int) (psrc-Numeric->Memory))) ; + nmark-- ; + ASSERT (E [e] == 0) ; + ASSERT (Work->Flublock == F1) ; + ASSERT (Work->Flblock == Work->Flublock + nb*nb) ; + ASSERT (Work->Fublock == Work->Flblock + dr*nb) ; + ASSERT (Work->Fcblock == Work->Fublock + nb*dc) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Work->Fcblock, dr, r, c) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Work->Flblock, dr, r, k); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Work->Fublock, dc, c, k) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Work->Flublock, nb, k, k) ; + ASSERT (r <= drnew && c <= dcnew && drnew <= dr && dcnew <= dc) ; +#endif + + /* compact frontal matrix to drnew-by-dcnew before moving it */ + + /* do not compact the LU block (nb-by-nb) */ + + /* compact the columns of L (from dr-by-nb to drnew-by-nb) */ + Fsrc = Work->Flblock ; + Fdst = Work->Flblock ; + ASSERT (Fdst == F1 + nb*nb) ; + gap1 = dr - r ; + gap2 = drnew - r ; + ASSERT (gap1 >= 0) ; + for (j = 0 ; j < k ; j++) + { + for (i = 0 ; i < r ; i++) + { + *Fdst++ = *Fsrc++ ; + } + Fsrc += gap1 ; + Fdst += gap2 ; + } + ASSERT (Fdst == F1 + nb*nb + drnew*k) ; + Fdst += drnew * (nb - k) ; + + /* compact the rows of U (U' from dc-by-nb to dcnew-by-nb) */ + Fsrc = Work->Fublock ; + ASSERT (Fdst == F1 + nb*nb + drnew*nb) ; + gap1 = dc - c ; + gap2 = dcnew - c ; + for (i = 0 ; i < k ; i++) + { + for (j = 0 ; j < c ; j++) + { + *Fdst++ = *Fsrc++ ; + } + Fsrc += gap1 ; + Fdst += gap2 ; + } + ASSERT (Fdst == F1 + nb*nb + drnew*nb + dcnew*k) ; + Fdst += dcnew * (nb - k) ; + + /* compact the columns of C (from dr-by-dc to drnew-by-dcnew) */ + Fsrc = Work->Fcblock ; + ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew) ; + gap1 = dr - r ; + gap2 = drnew - r ; + for (j = 0 ; j < c ; j++) + { + for (i = 0 ; i < r ; i++) + { + *Fdst++ = *Fsrc++ ; + } + Fsrc += gap1 ; + Fdst += gap2 ; + } + ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c) ; + + /* recompute Fcpos, if necessary */ + if (do_Fcpos) + { + Int *Fcols, *Fcpos ; + Fcols = Work->Fcols ; + Fcpos = Work->Fcpos ; + for (j = 0 ; j < c ; j++) + { + col = Fcols [j] ; + ASSERT (col >= 0 && col < Work->n_col) ; + ASSERT (Fcpos [col] == j * dr) ; + Fcpos [col] = j * drnew ; + } +#ifndef NDEBUG + { + Int cnt = 0 ; + for (j = 0 ; j < Work->n_col ; j++) + { + if (Fcpos [j] != EMPTY) cnt++ ; + } + DEBUGm2 (("Recompute Fcpos cnt "ID" c "ID"\n", cnt, c)) ; + ASSERT (cnt == c) ; + } +#endif + } + +#ifndef NDEBUG + DEBUGm2 (("Compacted front, drnew "ID" dcnew "ID"\n", drnew, dcnew)) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (F1 + nb*nb + drnew*nb + nb*dcnew, drnew, r, c) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (F1 + nb*nb, drnew, r, k) ; + DEBUG7 (("U block: ")) ; + UMF_dump_dense (F1 + nb*nb + drnew*nb, nb, k, c) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (F1, nb, k, k) ; +#endif + + /* Compacted dimensions of the new frontal matrix. */ + Work->fnr_curr = drnew ; + Work->fnc_curr = dcnew ; + Work->fcurr_size = (drnew + nb) * (dcnew + nb) ; + size = UNITS (Entry, Work->fcurr_size) ; + + /* make sure the object doesn't evaporate. The front can have + * zero size (Work->fcurr_size = 0), but the size of the memory + * block containing it cannot have zero size. */ + size = MAX (1, size) ; + + /* get the destination of frontal matrix */ + pnext->header.prevsize = size ; + pdest -= (size + 1) ; + F2 = (Entry *) (pdest + 1) ; + + ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ; + ASSERT (psrc <= pdest) ; + ASSERT (F1 <= F2) ; + + /* move the C block first */ + Fsrc = F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c ; + Fdst = F2 + nb*nb + drnew*nb + nb*dcnew + drnew*c ; + gap = drnew - r ; + for (j = c-1 ; j >= 0 ; j--) + { + Fsrc -= gap ; + Fdst -= gap ; + /* move column j of C */ + for (i = r-1 ; i >= 0 ; i--) + { + *--Fdst = *--Fsrc ; + } + } + ASSERT (Fsrc == F1 + nb*nb + drnew*nb + nb*dcnew) ; + ASSERT (Fdst == F2 + nb*nb + drnew*nb + nb*dcnew) ; + + /* move the U block */ + Fsrc -= dcnew * (nb - k) ; + Fdst -= dcnew * (nb - k) ; + ASSERT (Fsrc == F1 + nb*nb + drnew*nb + dcnew*k) ; + ASSERT (Fdst == F2 + nb*nb + drnew*nb + dcnew*k) ; + gap = dcnew - c ; + for (i = k-1 ; i >= 0 ; i--) + { + Fsrc -= gap ; + Fdst -= gap ; + for (j = c-1 ; j >= 0 ; j--) + { + *--Fdst = *--Fsrc ; + } + } + ASSERT (Fsrc == F1 + nb*nb + drnew*nb) ; + ASSERT (Fdst == F2 + nb*nb + drnew*nb) ; + + /* move the L block */ + Fsrc -= drnew * (nb - k) ; + Fdst -= drnew * (nb - k) ; + ASSERT (Fsrc == F1 + nb*nb + drnew*k) ; + ASSERT (Fdst == F2 + nb*nb + drnew*k) ; + gap = drnew - r ; + for (j = k-1 ; j >= 0 ; j--) + { + Fsrc -= gap ; + Fdst -= gap ; + for (i = r-1 ; i >= 0 ; i--) + { + *--Fdst = *--Fsrc ; + } + } + ASSERT (Fsrc == F1 + nb*nb) ; + ASSERT (Fdst == F2 + nb*nb) ; + + /* move the LU block */ + Fsrc -= nb * (nb - k) ; + Fdst -= nb * (nb - k) ; + ASSERT (Fsrc == F1 + nb*k) ; + ASSERT (Fdst == F2 + nb*k) ; + gap = nb - k ; + for (j = k-1 ; j >= 0 ; j--) + { + Fsrc -= gap ; + Fdst -= gap ; + for (i = k-1 ; i >= 0 ; i--) + { + *--Fdst = *--Fsrc ; + } + } + ASSERT (Fsrc == F1) ; + ASSERT (Fdst == F2) ; + + E [0] = (pdest + 1) - Numeric->Memory ; + + Work->Flublock = (Entry *) (Numeric->Memory + E [0]) ; + ASSERT (Work->Flublock == F2) ; + Work->Flblock = Work->Flublock + nb * nb ; + Work->Fublock = Work->Flblock + drnew * nb ; + Work->Fcblock = Work->Fublock + nb * dcnew ; + + pdest->header.prevsize = 0 ; + pdest->header.size = size ; + +#ifndef NDEBUG + DEBUG7 (("After moving compressed current frontal matrix:\n")) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Work->Fcblock, drnew, r, c) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Work->Flblock, drnew, r, k); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Work->Fublock, dcnew, c, k) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Work->Flublock, nb, k, k) ; +#endif + + } + else if (e > 0) + { + + /* -------------------------------------------------------------- */ + /* this is an element, compress and move from psrc down to pdest */ + /* -------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG7 (("\n")) ; + DEBUG7 ((ID":: Move element "ID": from: "ID" \n", + nmark, e, (Int) (psrc-Numeric->Memory))) ; + nmark-- ; + ASSERT (e <= nel) ; + ASSERT (E [e] == 0) ; +#endif + + /* -------------------------------------------------------------- */ + /* get the element scalars, and pointers to C, Rows, and Cols: */ + /* -------------------------------------------------------------- */ + + p = psrc + 1 ; + GET_ELEMENT (epsrc, p, Cols, Rows, ncols, nrows, C) ; + nrowsleft = epsrc->nrowsleft ; + ncolsleft = epsrc->ncolsleft ; + cdeg = epsrc->cdeg ; + rdeg = epsrc->rdeg ; + +#ifndef NDEBUG + DEBUG7 ((" nrows "ID" nrowsleft "ID"\n", nrows, nrowsleft)) ; + DEBUG7 ((" ncols "ID" ncolsleft "ID"\n", ncols, ncolsleft)) ; + DEBUG8 ((" Rows:")) ; + for (i = 0 ; i < nrows ; i++) DEBUG8 ((" "ID, Rows [i])) ; + DEBUG8 (("\n Cols:")) ; + for (j = 0 ; j < ncols ; j++) DEBUG8 ((" "ID, Cols [j])) ; + DEBUG8 (("\n")) ; +#endif + + /* -------------------------------------------------------------- */ + /* determine the layout of the new element */ + /* -------------------------------------------------------------- */ + + csize = nrowsleft * ncolsleft ; + size2 = UNITS (Element, 1) + + UNITS (Int, nrowsleft + ncolsleft) + + UNITS (Entry, csize) ; + + DEBUG7 (("Old size "ID" New size "ID"\n", size, size2)) ; + + pnext = pdest ; + pnext->header.prevsize = size2 ; + pdest -= (size2 + 1) ; + + ASSERT (size2 <= size) ; + ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ; + ASSERT (psrc <= pdest) ; + + p = pdest + 1 ; + epdest = (Element *) p ; + p += UNITS (Element, 1) ; + Cols2 = (Int *) p ; + Rows2 = Cols2 + ncolsleft ; + p += UNITS (Int, nrowsleft + ncolsleft) ; + C2 = (Entry *) p ; + + ASSERT (epdest >= epsrc) ; + ASSERT (Rows2 >= Rows) ; + ASSERT (Cols2 >= Cols) ; + ASSERT (C2 >= C) ; + ASSERT (p + UNITS (Entry, csize) == pnext) ; + + /* -------------------------------------------------------------- */ + /* move the contribution block */ + /* -------------------------------------------------------------- */ + + /* overlap = psrc + size + 1 > pdest ; */ + + if (nrowsleft < nrows || ncolsleft < ncols) + { + + /* ---------------------------------------------------------- */ + /* compress contribution block in place prior to moving it */ + /* ---------------------------------------------------------- */ + + DEBUG7 (("Compress C in place prior to move:\n")); +#ifndef NDEBUG + UMF_dump_dense (C, nrows, nrows, ncols) ; +#endif + C1 = C ; + C3 = C ; + for (j = 0 ; j < ncols ; j++) + { + if (Cols [j] >= 0) + { + for (i = 0 ; i < nrows ; i++) + { + if (Rows [i] >= 0) + { + *C3++ = C1 [i] ; + } + } + } + C1 += nrows ; + } + ASSERT (C3-C == csize) ; + DEBUG8 (("Newly compressed contrib. block (all in use):\n")) ; +#ifndef NDEBUG + UMF_dump_dense (C, nrowsleft, nrowsleft, ncolsleft) ; +#endif + } + + /* shift the contribution block down */ + C += csize ; + C2 += csize ; + for (i = 0 ; i < csize ; i++) + { + *--C2 = *--C ; + } + + /* -------------------------------------------------------------- */ + /* move the row indices */ + /* -------------------------------------------------------------- */ + + i2 = nrowsleft ; + for (i = nrows - 1 ; i >= 0 ; i--) + { + ASSERT (Rows2+i2 >= Rows+i) ; + if (Rows [i] >= 0) + { + Rows2 [--i2] = Rows [i] ; + } + } + ASSERT (i2 == 0) ; + + j2 = ncolsleft ; + for (j = ncols - 1 ; j >= 0 ; j--) + { + ASSERT (Cols2+j2 >= Cols+j) ; + if (Cols [j] >= 0) + { + Cols2 [--j2] = Cols [j] ; + } + } + ASSERT (j2 == 0) ; + + /* -------------------------------------------------------------- */ + /* construct the new header */ + /* -------------------------------------------------------------- */ + + /* E [0...e] is now valid */ + E [e] = (pdest + 1) - Numeric->Memory ; + epdest = (Element *) (pdest + 1) ; + + epdest->next = EMPTY ; /* destroys the son list */ + epdest->ncols = ncolsleft ; + epdest->nrows = nrowsleft ; + epdest->ncolsleft = ncolsleft ; + epdest->nrowsleft = nrowsleft ; + epdest->rdeg = rdeg ; + epdest->cdeg = cdeg ; + + ASSERT (size2 <= size) ; + pdest->header.prevsize = 0 ; + pdest->header.size = size2 ; + + DEBUG7 (("After moving it:\n")) ; +#ifndef NDEBUG + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + } + +#ifndef NDEBUG + else + { + DEBUG8 ((" free\n")) ; + } +#endif + DEBUG7 (("psrc "ID" tail "ID"\n", + (Int) (psrc-Numeric->Memory), Numeric->itail)) ; + } + + ASSERT (psrc == Numeric->Memory + Numeric->itail) ; + ASSERT (nmark == 0) ; + + /* ---------------------------------------------------------------------- */ + /* final tail pointer */ + /* ---------------------------------------------------------------------- */ + + ASSERT (pdest >= Numeric->Memory + Numeric->itail) ; + Numeric->itail = pdest - Numeric->Memory ; + pdest->header.prevsize = 0 ; + Numeric->ibig = EMPTY ; + Numeric->tail_usage = Numeric->size - Numeric->itail ; + + /* ---------------------------------------------------------------------- */ + /* clear the unused E [nel+1 .. Work->elen - 1] */ + /* ---------------------------------------------------------------------- */ + + for (e = nel+1 ; e < Work->elen ; e++) + { + E [e] = 0 ; + } + +#ifndef NDEBUG + UMF_dump_packed_memory (Numeric, Work) ; +#endif + + DEBUG8 (("::::GARBAGE COLLECTION DONE::::\n")) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.h b/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_garbage_collection.h @@ -0,0 +1,14 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_garbage_collection +( + NumericType *Numeric, + WorkType *Work, + Int drnew, + Int dcnew, + Int do_Fcpos +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.c b/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.c @@ -0,0 +1,222 @@ +/* ========================================================================== */ +/* === UMF_get_memory ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Reallocate the workspace (Numeric->Memory) and shift elements downwards. + needunits: increase in size so that the free space is at least this many + Units (to which the tuple lengths is added). + + Return TRUE if successful, FALSE if out of memory. +*/ + +#include "umf_internal.h" +#include "umf_garbage_collection.h" +#include "umf_tuple_lengths.h" +#include "umf_build_tuples.h" +#include "umf_mem_free_tail_block.h" +#include "umf_realloc.h" + +GLOBAL Int UMF_get_memory +( + NumericType *Numeric, + WorkType *Work, + Int needunits, + Int r2, /* compact current front to r2-by-c2 */ + Int c2, + Int do_Fcpos +) +{ + double nsize, bsize, tsize ; + Int i, minsize, newsize, newmem, costly, row, col, *Row_tlen, *Col_tlen, + n_row, n_col, *Row_degree, *Col_degree ; + Unit *mnew, *p ; + + /* ---------------------------------------------------------------------- */ + /* get and check parameters */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG1 (("::::GET MEMORY::::\n")) ; + UMF_dump_memory (Numeric) ; +#endif + + n_row = Work->n_row ; + n_col = Work->n_col ; + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_tlen = Numeric->Uilen ; + Col_tlen = Numeric->Lilen ; + + /* ---------------------------------------------------------------------- */ + /* initialize the tuple list lengths */ + /* ---------------------------------------------------------------------- */ + + for (row = 0 ; row < n_row ; row++) + { + if (NON_PIVOTAL_ROW (row)) + { + Row_tlen [row] = 0 ; + } + } + for (col = 0 ; col < n_col ; col++) + { + if (NON_PIVOTAL_COL (col)) + { + Col_tlen [col] = 0 ; + } + } + + /* ---------------------------------------------------------------------- */ + /* determine how much memory is needed for the tuples */ + /* ---------------------------------------------------------------------- */ + + nsize = (double) needunits + 2 ; + needunits += UMF_tuple_lengths (Numeric, Work, &tsize) ; + nsize += tsize ; + needunits += 2 ; /* add 2, so that newmem >= 2 is true if realloc'd */ + + /* note: Col_tlen and Row_tlen are updated, but the tuple lists */ + /* themselves are not. Do not attempt to scan the tuple lists. */ + /* They are now stale, and are about to be destroyed and recreated. */ + + /* ---------------------------------------------------------------------- */ + /* determine the desired new size of memory */ + /* ---------------------------------------------------------------------- */ + + DEBUG0 (("UMF_get_memory: needunits: "ID"\n", needunits)) ; + + minsize = Numeric->size + needunits ; + nsize += (double) Numeric->size ; + + bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ; + + newsize = (Int) (UMF_REALLOC_INCREASE * ((double) minsize)) ; + nsize *= UMF_REALLOC_INCREASE ; + nsize += 1 ; + + if (newsize < 0 || nsize > bsize) + { + /* :: realloc Numeric->Memory int overflow :: */ + DEBUGm3 (("Realloc hit integer limit\n")) ; + newsize = (Int) bsize ; /* we cannot increase the size beyond bsize */ + } + else + { + ASSERT (newsize <= nsize) ; + newsize = MAX (newsize, minsize) ; + } + newsize = MAX (newsize, Numeric->size) ; + + DEBUG0 (( + "REALLOC MEMORY: needunits "ID" old size: "ID" new size: "ID" Units \n", + needunits, Numeric->size, newsize)) ; + + /* Forget where the biggest free block is (we no longer need it) */ + /* since garbage collection will occur shortly. */ + Numeric->ibig = EMPTY ; + + DEBUG0 (("Before realloc E [0] "ID"\n", Work->E [0])) ; + + /* ---------------------------------------------------------------------- */ + /* reallocate the memory, if possible, and make it bigger */ + /* ---------------------------------------------------------------------- */ + + mnew = (Unit *) NULL ; + while (!mnew) + { + mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ; + if (!mnew) + { + if (newsize == minsize) /* last realloc attempt failed */ + { + /* We failed to get the minimum. Just stick with the */ + /* current allocation and hope that garbage collection */ + /* can recover enough space. */ + mnew = Numeric->Memory ; /* no new memory available */ + newsize = Numeric->size ; + } + else + { + /* otherwise, reduce the request and keep trying */ + newsize = (Int) (UMF_REALLOC_REDUCTION * ((double) newsize)) ; + newsize = MAX (minsize, newsize) ; + } + } + } + ASSERT (mnew != (Unit *) NULL) ; + + /* see if realloc had to copy, rather than just extend memory */ + costly = (mnew != Numeric->Memory) ; + + /* ---------------------------------------------------------------------- */ + /* extend the tail portion of memory downwards */ + /* ---------------------------------------------------------------------- */ + + Numeric->Memory = mnew ; + if (Work->E [0]) + { + Int nb, dr, dc ; + nb = Work->nb ; + dr = Work->fnr_curr ; + dc = Work->fnc_curr ; + Work->Flublock = (Entry *) (Numeric->Memory + Work->E [0]) ; + Work->Flblock = Work->Flublock + nb * nb ; + Work->Fublock = Work->Flblock + dr * nb ; + Work->Fcblock = Work->Fublock + nb * dc ; + DEBUG0 (("after realloc E [0] "ID"\n", Work->E [0])) ; + } + ASSERT (IMPLIES (!(Work->E [0]), Work->Flublock == (Entry *) NULL)) ; + + newmem = newsize - Numeric->size ; + ASSERT (newmem == 0 || newmem >= 2) ; + + if (newmem >= 2) + { + /* reallocation succeeded */ + + /* point to the old tail marker block of size 1 + header */ + p = Numeric->Memory + Numeric->size - 2 ; + + /* create a new block out of the newly extended memory */ + p->header.size = newmem - 1 ; + i = Numeric->size - 1 ; + p += newmem ; + + /* create a new tail marker block */ + p->header.prevsize = newmem - 1 ; + p->header.size = 1 ; + + Numeric->size = newsize ; + + /* free the new block */ + UMF_mem_free_tail_block (Numeric, i) ; + + Numeric->nrealloc++ ; + + if (costly) + { + Numeric->ncostly++ ; + } + + } + DEBUG1 (("Done with realloc memory\n")) ; + + /* ---------------------------------------------------------------------- */ + /* garbage collection on the tail of Numeric->memory (destroys tuples) */ + /* ---------------------------------------------------------------------- */ + + UMF_garbage_collection (Numeric, Work, r2, c2, do_Fcpos) ; + + /* ---------------------------------------------------------------------- */ + /* rebuild the tuples */ + /* ---------------------------------------------------------------------- */ + + return (UMF_build_tuples (Numeric, Work)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.h b/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_get_memory.h @@ -0,0 +1,15 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_get_memory +( + NumericType *Numeric, + WorkType *Work, + Int needunits, + Int r2, + Int c2, + Int do_Fcpos +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.c b/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.c @@ -0,0 +1,293 @@ +/* ========================================================================== */ +/* === UMF_grow_front ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Current frontal matrix is too small. Make it bigger. */ + +#include "umf_internal.h" +#include "umf_mem_free_tail_block.h" +#include "umf_mem_alloc_tail_block.h" +#include "umf_get_memory.h" + +GLOBAL Int UMF_grow_front +( + NumericType *Numeric, + Int fnr2, /* desired size is fnr2-by-fnc2 */ + Int fnc2, + WorkType *Work, + Int do_what /* -1: UMF_start_front + * 0: UMF_init_front, do not recompute Fcpos + * 1: UMF_extend_front + * 2: UMF_init_front, recompute Fcpos */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double s ; + Entry *Fcold, *Fcnew ; + Int j, i, col, *Fcpos, *Fcols, fnrows_max, fncols_max, fnr_curr, nb, + fnrows_new, fncols_new, fnr_min, fnc_min, minsize, + newsize, fnrows, fncols, *E, eloc ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + if (do_what != -1) UMF_debug++ ; + DEBUG0 (("\n\n====================GROW FRONT: do_what: "ID"\n", do_what)) ; + if (do_what != -1) UMF_debug-- ; + ASSERT (Work->do_grow) ; + ASSERT (Work->fnpiv == 0) ; +#endif + + Fcols = Work->Fcols ; + Fcpos = Work->Fcpos ; + E = Work->E ; + + /* ---------------------------------------------------------------------- */ + /* The current front is too small, find the new size */ + /* ---------------------------------------------------------------------- */ + + /* maximum size of frontal matrix for this chain */ + nb = Work->nb ; + fnrows_max = Work->fnrows_max + nb ; + fncols_max = Work->fncols_max + nb ; + ASSERT (fnrows_max >= 0 && (fnrows_max % 2) == 1) ; + DEBUG0 (("Max size: "ID"-by-"ID" (incl. "ID" pivot block\n", + fnrows_max, fncols_max, nb)) ; + + /* current dimensions of frontal matrix: fnr-by-fnc */ + DEBUG0 (("Current : "ID"-by-"ID" (excl "ID" pivot blocks)\n", + Work->fnr_curr, Work->fnc_curr, nb)) ; + ASSERT (Work->fnr_curr >= 0) ; + ASSERT ((Work->fnr_curr % 2 == 1) || Work->fnr_curr == 0) ; + + /* required dimensions of frontal matrix: fnr_min-by-fnc_min */ + fnrows_new = Work->fnrows_new + 1 ; + fncols_new = Work->fncols_new + 1 ; + ASSERT (fnrows_new >= 0) ; + if (fnrows_new % 2 == 0) fnrows_new++ ; + fnrows_new += nb ; + fncols_new += nb ; + fnr_min = MIN (fnrows_new, fnrows_max) ; + fnc_min = MIN (fncols_new, fncols_max) ; + minsize = fnr_min * fnc_min ; + if (INT_OVERFLOW ((double) fnr_min * (double) fnc_min * sizeof (Entry))) + { + /* :: the minimum front size is bigger than the integer maximum :: */ + return (FALSE) ; + } + ASSERT (fnr_min >= 0) ; + ASSERT (fnr_min % 2 == 1) ; + + DEBUG0 (("Min : "ID"-by-"ID"\n", fnr_min, fnc_min)) ; + + /* grow the front to fnr2-by-fnc2, but no bigger than the maximum, + * and no smaller than the minumum. */ + DEBUG0 (("Desired : ("ID"+"ID")-by-("ID"+"ID")\n", fnr2, nb, fnc2, nb)) ; + fnr2 += nb ; + fnc2 += nb ; + ASSERT (fnr2 >= 0) ; + if (fnr2 % 2 == 0) fnr2++ ; + fnr2 = MAX (fnr2, fnr_min) ; + fnc2 = MAX (fnc2, fnc_min) ; + fnr2 = MIN (fnr2, fnrows_max) ; + fnc2 = MIN (fnc2, fncols_max) ; + DEBUG0 (("Try : "ID"-by-"ID"\n", fnr2, fnc2)) ; + ASSERT (fnr2 >= 0) ; + ASSERT (fnr2 % 2 == 1) ; + + s = ((double) fnr2) * ((double) fnc2) ; + if (INT_OVERFLOW (s * sizeof (Entry))) + { + /* :: frontal matrix size int overflow :: */ + /* the desired front size is bigger than the integer maximum */ + /* compute a such that a*a*s < Int_MAX / sizeof (Entry) */ + double a = 0.9 * sqrt ((Int_MAX / sizeof (Entry)) / s) ; + fnr2 = MAX (fnr_min, a * fnr2) ; + fnc2 = MAX (fnc_min, a * fnc2) ; + /* the new frontal size is a*r*a*c = a*a*s */ + newsize = fnr2 * fnc2 ; + ASSERT (fnr2 >= 0) ; + if (fnr2 % 2 == 0) fnr2++ ; + fnc2 = newsize / fnr2 ; + } + + fnr2 = MAX (fnr2, fnr_min) ; + fnc2 = MAX (fnc2, fnc_min) ; + newsize = fnr2 * fnc2 ; + + ASSERT (fnr2 >= 0) ; + ASSERT (fnr2 % 2 == 1) ; + ASSERT (fnr2 >= fnr_min) ; + ASSERT (fnc2 >= fnc_min) ; + ASSERT (newsize >= minsize) ; + + /* ---------------------------------------------------------------------- */ + /* free the current front if it is empty of any numerical values */ + /* ---------------------------------------------------------------------- */ + + if (E [0] && do_what != 1) + { + /* free the current front, if it exists and has nothing in it */ + DEBUG0 (("Freeing empty front\n")) ; + UMF_mem_free_tail_block (Numeric, E [0]) ; + E [0] = 0 ; + Work->Flublock = (Entry *) NULL ; + Work->Flblock = (Entry *) NULL ; + Work->Fublock = (Entry *) NULL ; + Work->Fcblock = (Entry *) NULL ; + } + + /* ---------------------------------------------------------------------- */ + /* allocate the new front, doing garbage collection if necessary */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) /* a double relop, but ignore NaN case */ + { + double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ; + DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random garbage collection (grow)\n")) ; + } +#endif + + DEBUG0 (("Attempt size: "ID"-by-"ID"\n", fnr2, fnc2)) ; + eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ; + + if (!eloc) + { + /* Do garbage collection, realloc, and try again. Compact the current + * contribution block in the front to fnrows-by-fncols. Note that + * there are no pivot rows/columns in current front. Do not recompute + * Fcpos in UMF_garbage_collection. */ + DEBUGm3 (("get_memory from umf_grow_front\n")) ; + if (!UMF_get_memory (Numeric, Work, 1 + UNITS (Entry, newsize), + Work->fnrows, Work->fncols, FALSE)) + { + /* :: out of memory in umf_grow_front :: */ + return (FALSE) ; /* out of memory */ + } + DEBUG0 (("Attempt size: "ID"-by-"ID" again\n", fnr2, fnc2)) ; + eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ; + } + + /* try again with something smaller */ + while ((fnr2 != fnr_min || fnc2 != fnc_min) && !eloc) + { + fnr2 = MIN (fnr2 - 2, fnr2 * UMF_REALLOC_REDUCTION) ; + fnc2 = MIN (fnc2 - 2, fnc2 * UMF_REALLOC_REDUCTION) ; + ASSERT (fnr_min >= 0) ; + ASSERT (fnr_min % 2 == 1) ; + fnr2 = MAX (fnr_min, fnr2) ; + fnc2 = MAX (fnc_min, fnc2) ; + ASSERT (fnr2 >= 0) ; + if (fnr2 % 2 == 0) fnr2++ ; + newsize = fnr2 * fnc2 ; + DEBUGm3 (("Attempt smaller size: "ID"-by-"ID" minsize "ID"-by-"ID"\n", + fnr2, fnc2, fnr_min, fnc_min)) ; + eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ; + } + + /* try again with the smallest possible size */ + if (!eloc) + { + fnr2 = fnr_min ; + fnc2 = fnc_min ; + newsize = minsize ; + DEBUG0 (("Attempt minsize: "ID"-by-"ID"\n", fnr2, fnc2)) ; + eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ; + } + + if (!eloc) + { + /* out of memory */ + return (FALSE) ; + } + + ASSERT (fnr2 >= 0) ; + ASSERT (fnr2 % 2 == 1) ; + ASSERT (fnr2 >= fnr_min && fnc2 >= fnc_min) ; + + /* ---------------------------------------------------------------------- */ + /* copy the old frontal matrix into the new one */ + /* ---------------------------------------------------------------------- */ + + /* old contribution block (if any) */ + fnr_curr = Work->fnr_curr ; /* garbage collection can change fn*_curr */ + ASSERT (fnr_curr >= 0) ; + ASSERT ((fnr_curr % 2 == 1) || fnr_curr == 0) ; + fnrows = Work->fnrows ; + fncols = Work->fncols ; + Fcold = Work->Fcblock ; + + /* remove nb from the sizes */ + fnr2 -= nb ; + fnc2 -= nb ; + + /* new frontal matrix */ + Work->Flublock = (Entry *) (Numeric->Memory + eloc) ; + Work->Flblock = Work->Flublock + nb * nb ; + Work->Fublock = Work->Flblock + nb * fnr2 ; + Work->Fcblock = Work->Fublock + nb * fnc2 ; + Fcnew = Work->Fcblock ; + + if (E [0]) + { + /* copy the old contribution block into the new one */ + for (j = 0 ; j < fncols ; j++) + { + col = Fcols [j] ; + DEBUG1 (("copy col "ID" \n",col)) ; + ASSERT (col >= 0 && col < Work->n_col) ; + for (i = 0 ; i < fnrows ; i++) + { + Fcnew [i] = Fcold [i] ; + } + Fcnew += fnr2 ; + Fcold += fnr_curr ; + DEBUG1 (("new offset col "ID" "ID"\n",col, j * fnr2)) ; + Fcpos [col] = j * fnr2 ; + } + } + else if (do_what == 2) + { + /* just find the new column offsets */ + for (j = 0 ; j < fncols ; j++) + { + col = Fcols [j] ; + DEBUG1 (("new offset col "ID" "ID"\n",col, j * fnr2)) ; + Fcpos [col] = j * fnr2 ; + } + } + + /* free the old frontal matrix */ + UMF_mem_free_tail_block (Numeric, E [0]) ; + + /* ---------------------------------------------------------------------- */ + /* new frontal matrix size */ + /* ---------------------------------------------------------------------- */ + + E [0] = eloc ; + Work->fnr_curr = fnr2 ; /* C block is fnr2-by-fnc2 */ + Work->fnc_curr = fnc2 ; + Work->fcurr_size = newsize ; /* including LU, L, U, and C blocks */ + Work->do_grow = FALSE ; /* the front has just been grown */ + + ASSERT (Work->fnr_curr >= 0) ; + ASSERT (Work->fnr_curr % 2 == 1) ; + DEBUG0 (("Newly grown front: "ID"+"ID" by "ID"+"ID"\n", Work->fnr_curr, + nb, Work->fnc_curr, nb)) ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.h b/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_grow_front.h @@ -0,0 +1,14 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_grow_front +( + NumericType *Numeric, + Int fnr2, + Int fnc2, + WorkType *Work, + Int do_what +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.c b/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.c @@ -0,0 +1,267 @@ +/* ========================================================================== */ +/* === UMF_init_front ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include "umf_internal.h" +#include "umf_grow_front.h" + +/* ========================================================================== */ +/* === zero_init_front ====================================================== */ +/* ========================================================================== */ + +/* Set the initial frontal matrix to zero. */ + +PRIVATE void zero_init_front (Int m, Int n, Entry *Fcblock, Int d) +{ + Int i, j ; + Entry *F, *Fj = Fcblock ; + for (j = 0 ; j < m ; j++) + { + F = Fj ; + Fj += d ; + for (i = 0 ; i < n ; i++) + { + /* CLEAR (Fcblock [i + j*d]) ; */ + CLEAR (*F) ; + F++ ; + } + } +} + +/* ========================================================================== */ +/* === UMF_init_front ======================================================= */ +/* ========================================================================== */ + +GLOBAL Int UMF_init_front +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int i, j, fnr_curr, row, col, *Frows, *Fcols, + *Fcpos, *Frpos, fncols, fnrows, *Wrow, fnr2, fnc2, rrdeg, ccdeg, *Wm, + fnrows_extended ; + Entry *Fcblock, *Fl, *Wy, *Wx ; + + /* ---------------------------------------------------------------------- */ + /* get current frontal matrix and check for frontal growth */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG0 (("INIT FRONT\n")) ; + DEBUG1 (("CURR before init:\n")) ; + UMF_dump_current_front (Numeric, Work, FALSE) ; +#endif + if (Work->do_grow) + { + fnr2 = UMF_FRONTAL_GROWTH * Work->fnrows_new + 2 ; + fnc2 = UMF_FRONTAL_GROWTH * Work->fncols_new + 2 ; + if (!UMF_grow_front (Numeric, fnr2, fnc2, Work, + Work->pivrow_in_front ? 2 : 0)) + { + /* :: out of memory in umf_init_front :: */ + DEBUGm4 (("out of memory: init front\n")) ; + return (FALSE) ; + } + } +#ifndef NDEBUG + DEBUG1 (("CURR after grow:\n")) ; + UMF_dump_current_front (Numeric, Work, FALSE) ; + DEBUG1 (("fnrows new "ID" fncols new "ID"\n", + Work->fnrows_new, Work->fncols_new)) ; +#endif + ASSERT (Work->fnpiv == 0) ; + fnr_curr = Work->fnr_curr ; + ASSERT (Work->fnrows_new + 1 <= fnr_curr) ; + ASSERT (Work->fncols_new + 1 <= Work->fnc_curr) ; + ASSERT (fnr_curr >= 0) ; + ASSERT (fnr_curr % 2 == 1) ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + /* current front is defined by pivot row and column */ + + Frows = Work->Frows ; + Fcols = Work->Fcols ; + Frpos = Work->Frpos ; + Fcpos = Work->Fcpos ; + + Work->fnzeros = 0 ; + + ccdeg = Work->ccdeg ; + rrdeg = Work->rrdeg ; + + fnrows = Work->fnrows ; + fncols = Work->fncols ; + + /* if both pivrow and pivcol are in front, then we extend the old one */ + /* in UMF_extend_front, rather than starting a new one here. */ + ASSERT (! (Work->pivrow_in_front && Work->pivcol_in_front)) ; + + /* ---------------------------------------------------------------------- */ + /* place pivot column pattern in frontal matrix */ + /* ---------------------------------------------------------------------- */ + + Fl = Work->Flblock ; + + if (Work->pivcol_in_front) + { + /* Append the pivot column extension. + * Note that all we need to do is increment the size, since the + * candidate pivot column pattern is already in place in + * Frows [0 ... fnrows-1] (the old pattern), and + * Frows [fnrows ... fnrows + Work->ccdeg - 1] (the new + * pattern). Frpos is also properly defined. */ + /* make a list of the new rows to scan */ + Work->fscan_row = fnrows ; /* only scan the new rows */ + Work->NewRows = Work->Wrp ; + Wy = Work->Wy ; + for (i = 0 ; i < fnrows ; i++) + { + Fl [i] = Wy [i] ; + } + fnrows_extended = fnrows + ccdeg ; + for (i = fnrows ; i < fnrows_extended ; i++) + { + Fl [i] = Wy [i] ; + /* flip the row index, since Wrp must be < 0 */ + row = Frows [i] ; + Work->NewRows [i] = FLIP (row) ; + } + fnrows = fnrows_extended ; + } + else + { + /* this is a completely new column */ + Work->fscan_row = 0 ; /* scan all the rows */ + Work->NewRows = Frows ; + Wm = Work->Wm ; + Wx = Work->Wx ; + for (i = 0 ; i < ccdeg ; i++) + { + Fl [i] = Wx [i] ; + row = Wm [i] ; + Frows [i] = row ; + Frpos [row] = i ; + } + fnrows = ccdeg ; + } + + Work->fnrows = fnrows ; + +#ifndef NDEBUG + DEBUG3 (("New Pivot col "ID" now in front, length "ID"\n", + Work->pivcol, fnrows)) ; + for (i = 0 ; i < fnrows ; i++) + { + DEBUG4 ((" "ID": row "ID"\n", i, Frows [i])) ; + ASSERT (Frpos [Frows [i]] == i) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* place pivot row pattern in frontal matrix */ + /* ---------------------------------------------------------------------- */ + + Wrow = Work->Wrow ; + if (Work->pivrow_in_front) + { + /* append the pivot row extension */ + Work->fscan_col = fncols ; /* only scan the new columns */ + Work->NewCols = Work->Wp ; +#ifndef NDEBUG + for (j = 0 ; j < fncols ; j++) + { + col = Fcols [j] ; + ASSERT (col >= 0 && col < Work->n_col) ; + ASSERT (Fcpos [col] == j * fnr_curr) ; + } +#endif + /* Wrow == Fcol for the IN_IN case, and for the OUT_IN case when + * the pivrow [IN][IN] happens to be the same as pivrow [OUT][IN]. + * See UMF_local_search for more details. */ + ASSERT (IMPLIES (Work->pivcol_in_front, Wrow == Fcols)) ; + if (Wrow == Fcols) + { + for (j = fncols ; j < rrdeg ; j++) + { + col = Wrow [j] ; + /* Fcols [j] = col ; not needed */ + /* flip the col index, since Wp must be < 0 */ + Work->NewCols [j] = FLIP (col) ; + Fcpos [col] = j * fnr_curr ; + } + } + else + { + for (j = fncols ; j < rrdeg ; j++) + { + col = Wrow [j] ; + Fcols [j] = col ; + /* flip the col index, since Wp must be < 0 */ + Work->NewCols [j] = FLIP (col) ; + Fcpos [col] = j * fnr_curr ; + } + } + } + else + { + /* this is a completely new row */ + Work->fscan_col = 0 ; /* scan all the columns */ + Work->NewCols = Fcols ; + for (j = 0 ; j < rrdeg ; j++) + { + col = Wrow [j] ; + Fcols [j] = col ; + Fcpos [col] = j * fnr_curr ; + } + } + + DEBUGm1 (("rrdeg "ID" fncols "ID"\n", rrdeg, fncols)) ; + fncols = rrdeg ; + Work->fncols = fncols ; + + /* ---------------------------------------------------------------------- */ + /* clear the frontal matrix */ + /* ---------------------------------------------------------------------- */ + + ASSERT (fnrows == Work->fnrows_new + 1) ; + ASSERT (fncols == Work->fncols_new + 1) ; + + Fcblock = Work->Fcblock ; + ASSERT (Fcblock != (Entry *) NULL) ; + + zero_init_front (fncols, fnrows, Fcblock, fnr_curr) ; + +#ifndef NDEBUG + DEBUG3 (("New Pivot row "ID" now in front, length "ID" fnr_curr "ID"\n", + Work->pivrow, fncols, fnr_curr)) ; + for (j = 0 ; j < fncols ; j++) + { + DEBUG4 (("col "ID" position "ID"\n", j, Fcols [j])) ; + ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* current workspace usage: */ + /* ---------------------------------------------------------------------- */ + + /* Fcblock [0..fnr_curr-1, 0..fnc_curr-1]: space for the new frontal + * matrix. Fcblock (i,j) is located at Fcblock [i+j*fnr_curr] */ + + return (TRUE) ; + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.h b/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_init_front.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_init_front +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_internal.h b/liboctave/UMFPACK/UMFPACK/Source/umf_internal.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_internal.h @@ -0,0 +1,760 @@ +/* ========================================================================== */ +/* === umf_internal.h ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + This file is for internal use in UMFPACK itself, and should not be included + in user code. Use umfpack.h instead. User-accessible file names and + routine names all start with the letters "umfpack_". Non-user-accessible + file names and routine names all start with "umf_". +*/ + +#ifndef _UMF_INTERNAL +#define _UMF_INTERNAL + +/* -------------------------------------------------------------------------- */ +/* ANSI standard include files */ +/* -------------------------------------------------------------------------- */ + +/* from float.h: DBL_EPSILON */ +#include + +/* from string.h: strcmp */ +#include + +/* when debugging, assert.h and the assert macro are used (see umf_dump.h) */ + +/* -------------------------------------------------------------------------- */ +/* Architecture */ +/* -------------------------------------------------------------------------- */ + +#if defined (__sun) || defined (MSOL2) || defined (ARCH_SOL2) +#define UMF_SOL2 +#define UMFPACK_ARCHITECTURE "Sun Solaris" + +#elif defined (__sgi) || defined (MSGI) || defined (ARCH_SGI) +#define UMF_SGI +#define UMFPACK_ARCHITECTURE "SGI Irix" + +#elif defined (__linux) || defined (MGLNX86) || defined (ARCH_GLNX86) +#define UMF_LINUX +#define UMFPACK_ARCHITECTURE "Linux" + +#elif defined (_AIX) || defined (MIBM_RS) || defined (ARCH_IBM_RS) +#define UMF_AIX +#define UMFPACK_ARCHITECTURE "IBM AIX" + +#elif defined (__alpha) || defined (MALPHA) || defined (ARCH_ALPHA) +#define UMF_ALPHA +#define UMFPACK_ARCHITECTURE "Compaq Alpha" + +#elif defined (__WIN32) || defined (_WIN32) || defined (_win32) || defined (__win32) || defined (WIN32) +#define UMF_WINDOWS +#define UMFPACK_ARCHITECTURE "Microsoft Windows" + +#elif defined (__hppa) || defined (__hpux) || defined (MHPUX) || defined (ARCH_HPUX) +#define UMF_HP +#define UMFPACK_ARCHITECTURE "HP Unix" + +#elif defined (__hp700) || defined (MHP700) || defined (ARCH_HP700) +#define UMF_HP +#define UMFPACK_ARCHITECTURE "HP 700 Unix" + +#else +/* If the architecture is unknown, and you call the BLAS, you may need to */ +/* define BLAS_BY_VALUE, BLAS_NO_UNDERSCORE, and/or BLAS_CHAR_ARG yourself. */ +#define UMFPACK_ARCHITECTURE "unknown" +#endif + + +/* -------------------------------------------------------------------------- */ +/* basic definitions (see also amd_internal.h) */ +/* -------------------------------------------------------------------------- */ + +#define ONES_COMPLEMENT(r) (-(r)-1) + +/* -------------------------------------------------------------------------- */ +/* AMD include file */ +/* -------------------------------------------------------------------------- */ + +/* stdio.h, stdlib.h, limits.h, and math.h, NDEBUG definition, + * assert.h, and MATLAB include files */ +#include "amd_internal.h" + +/* -------------------------------------------------------------------------- */ +/* Real/complex and int/long definitions, double relops */ +/* -------------------------------------------------------------------------- */ + +#include "umf_version.h" + +/* -------------------------------------------------------------------------- */ +/* Compile-time configurations */ +/* -------------------------------------------------------------------------- */ + +#include "umf_config.h" + +/* -------------------------------------------------------------------------- */ +/* umfpack include file */ +/* -------------------------------------------------------------------------- */ + +#include "umfpack.h" + +/* -------------------------------------------------------------------------- */ +/* for contents of Info. This must correlate with umfpack.h */ +/* -------------------------------------------------------------------------- */ + +#define ESTIMATE (UMFPACK_NUMERIC_SIZE_ESTIMATE - UMFPACK_NUMERIC_SIZE) +#define ACTUAL 0 + +/* -------------------------------------------------------------------------- */ +/* get a parameter from the Control array */ +/* -------------------------------------------------------------------------- */ + +#define GET_CONTROL(i,default) \ + ((Control != (double *) NULL) ? \ + (SCALAR_IS_NAN (Control [i]) ? default : Control [i]) \ + : default) + +/* -------------------------------------------------------------------------- */ +/* for clearing the external degree counters */ +/* -------------------------------------------------------------------------- */ + +#define MAX_MARK(n) Int_MAX - (2*(n)+1) + +/* -------------------------------------------------------------------------- */ +/* convert number of Units to MBytes */ +/* -------------------------------------------------------------------------- */ + +#define MBYTES(units) (((units) * sizeof (Unit)) / 1048576.0) + +/* -------------------------------------------------------------------------- */ +/* dense row/column macro */ +/* -------------------------------------------------------------------------- */ + +/* In order for a row or column to be treated as "dense", it must have more */ +/* entries than the value returned by this macro. n is the dimension of the */ +/* matrix, and alpha is the dense row/column control parameter. */ + +/* Note: this is not defined if alpha is NaN or Inf: */ +#define UMFPACK_DENSE_DEGREE_THRESHOLD(alpha,n) \ + ((Int) MAX (16.0, (alpha) * 16.0 * sqrt ((double) (n)))) + +/* -------------------------------------------------------------------------- */ +/* PRINTF */ +/* -------------------------------------------------------------------------- */ + +#define PRINTFk(k,params) { if (prl >= (k)) { PRINTF (params) ; } } +#define PRINTF1(params) PRINTFk (1, params) +#define PRINTF2(params) PRINTFk (2, params) +#define PRINTF3(params) PRINTFk (3, params) +#define PRINTF4(params) PRINTFk (4, params) +#define PRINTF5(params) PRINTFk (5, params) +#define PRINTF6(params) PRINTFk (6, params) + +/* -------------------------------------------------------------------------- */ +/* Fixed control parameters */ +/* -------------------------------------------------------------------------- */ + +/* maximum number of columns to consider at one time, in a single front */ +#define MAX_CANDIDATES 128 + +/* reduce Numeric->Memory request by this ratio, if allocation fails */ +#define UMF_REALLOC_REDUCTION (0.95) + +/* increase Numeric->Memory request by this ratio, if we need more */ +#define UMF_REALLOC_INCREASE (1.2) + +/* increase the dimensions of the current frontal matrix by this factor + * when it needs to grow. */ +#define UMF_FRONTAL_GROWTH (1.2) + +/* largest BLAS block size permitted */ +#define MAXNB 64 + +/* if abs (y) < RECIPROCAL_TOLERANCE, then compute x/y. Otherwise x*(1/y). + * Ignored if NRECIPROCAL is defined */ +#define RECIPROCAL_TOLERANCE 1e-12 + +/* -------------------------------------------------------------------------- */ +/* Memory allocator */ +/* -------------------------------------------------------------------------- */ + +/* The MATLAB mexFunction uses MATLAB's memory manager, while the C-callable + * AMD library uses the ANSI C malloc, free, and realloc routines. To use + * the mx* memory allocation routines, use -DNUTIL when compiling. + */ + +#undef ALLOCATE +#undef FREE +#undef REALLOC + +#ifdef MATLAB_MEX_FILE + +#ifdef NUTIL + +/* These functions simply terminate the mexFunction if they fail to allocate + * memory. That's too restrictive for UMFPACK. */ +#define ALLOCATE mxMalloc +#define FREE mxFree +#define REALLOCATE mxRealloc + +#else + +/* Use internal MATLAB memory allocation routines, used by built-in MATLAB + * functions. These are not documented, but are available for use. Their + * prototypes are in util.h, but that file is not provided to the MATLAB user. + * The advantage of using these routines is that they return NULL if out of + * memory, instead of terminating the mexFunction. UMFPACK attempts to allocate + * extra space for "elbow room", and then reduces its request if the memory is + * not available. That strategy doesn't work with the mx* routines. + */ +void *utMalloc (size_t size) ; +void utFree (void *p) ; +void *utRealloc (void *p, size_t size) ; +#define ALLOCATE utMalloc +#define FREE utFree +#define REALLOCATE utRealloc + +#endif +#else +#ifdef MATHWORKS + +/* Compiling as a built-in routine. Since out-of-memory conditions are checked + * after every allocation, we can use ut* routines here. */ +#define ALLOCATE utMalloc +#define FREE utFree +#define REALLOCATE utRealloc + +#else + +/* use the ANSI C memory allocation routines */ +#define ALLOCATE malloc +#define FREE free +#define REALLOCATE realloc + +#endif +#endif + +/* -------------------------------------------------------------------------- */ +/* Memory space definitions */ +/* -------------------------------------------------------------------------- */ + +/* for memory alignment - assume double has worst case alignment */ +typedef double Align ; + +/* get number of bytes required to hold n items of a type: */ +/* note that this will not overflow, because sizeof (type) is always */ +/* greater than or equal to sizeof (Int) >= 2 */ +#define BYTES(type,n) (sizeof (type) * (n)) + +/* ceiling of (b/u). Assumes b >= 0 and u > 0 */ +#define CEILING(b,u) (((b) + (u) - 1) / (u)) + +/* get number of Units required to hold n items of a type: */ +#define UNITS(type,n) (CEILING (BYTES (type, n), sizeof (Unit))) + +/* same as DUNITS, but use double instead of int to avoid overflow */ +#define DUNITS(type,n) (ceil (BYTES (type, (double) n) / sizeof (Unit))) + +union Unit_union +{ /* memory is allocated in multiples of Unit */ + struct + { + Int + size, /* size, in Units, of the block, excl. header block */ + /* size >= 0: block is in use */ + /* size < 0: block is free, of |size| Units */ + prevsize ; /* size, in Units, of preceding block in S->Memory */ + /* during garbage_collection, prevsize is set to -e-1 */ + /* for element e, or positive (and thus a free block) */ + /* otherwise */ + } header ; /* block header */ + Align xxxxxx ; /* force alignment of blocks (xxxxxx is never used) */ +} ; + +typedef union Unit_union Unit ; + +/* get the size of an allocated block */ +#define GET_BLOCK_SIZE(p) (((p)-1)->header.size) + +/* -------------------------------------------------------------------------- */ +/* Numeric */ +/* -------------------------------------------------------------------------- */ + +/* + NUMERIC_VALID and SYMBOLIC_VALID: + The different values of SYBOLIC_VALID and NUMERIC_VALID are chosen as a + first defense against corrupted *Symbolic or *Numeric pointers passed to an + UMFPACK routine. They also ensure that the objects are used only by the + same version that created them (umfpack_di_*, umfpack_dl_*, umfpack_zi_*, + or umfpack_zl_*). The values have also been changed since prior releases of + the code to ensure that all routines that operate on the objects are of the + same release. The values themselves are purely arbitrary. The are less + than the ANSI C required minimums of INT_MAX and LONG_MAX, respectively. +*/ + +#ifdef DINT +#define NUMERIC_VALID 15977 +#define SYMBOLIC_VALID 41937 +#endif +#ifdef DLONG +#define NUMERIC_VALID 399789720 +#define SYMBOLIC_VALID 399192713 +#endif +#ifdef ZINT +#define NUMERIC_VALID 17957 +#define SYMBOLIC_VALID 40927 +#endif +#ifdef ZLONG +#define NUMERIC_VALID 129987754 +#define SYMBOLIC_VALID 110291734 +#endif + +typedef struct /* NumericType */ +{ + double + flops, /* "true" flop count */ + relpt, /* relative pivot tolerance used */ + relpt2, /* relative pivot tolerance used for sym. */ + droptol, + alloc_init, /* initial allocation of Numeric->memory */ + front_alloc_init, /* frontal matrix allocation parameter */ + rsmin, /* smallest row sum */ + rsmax, /* largest row sum */ + min_udiag, /* smallest abs value on diagonal of D */ + max_udiag, /* smallest abs value on diagonal of D */ + rcond ; /* min (D) / max (D) */ + + Int + scale ; + + Int valid ; /* set to NUMERIC_VALID, for validity check */ + + /* Memory space for A and LU factors */ + Unit + *Memory ; /* working memory for A and LU factors */ + Int + ihead, /* pointer to tail of LU factors, in Numeric->Memory */ + itail, /* pointer to top of elements & tuples, */ + /* in Numeric->Memory */ + ibig, /* pointer to largest free block seen in tail */ + size ; /* size of Memory, in Units */ + + Int + *Rperm, /* pointer to row perm array, size: n+1 */ + /* after UMF_kernel: Rperm [new] = old */ + /* during UMF_kernel: Rperm [old] = new */ + *Cperm, /* pointer to col perm array, size: n+1 */ + /* after UMF_kernel: Cperm [new] = old */ + /* during UMF_kernel: Cperm [old] = new */ + + *Upos, /* see UMFPACK_get_numeric for a description */ + *Lpos, + *Lip, + *Lilen, + *Uip, + *Uilen, + *Upattern ; /* pattern of last row of U (if singular) */ + + Int + ulen, /* length of Upattern */ + npiv, /* number of structural pivots found (sprank approx) */ + nnzpiv ; /* number of numerical (nonzero) pivots found */ + + Entry + *D ; /* D [i] is the diagonal entry of U */ + + Int do_recip ; + double *Rs ; /* scale factors for the rows of A and b */ + /* do_recip FALSE: Divide row i by Rs [i] */ + /* do_recip TRUE: Multiply row i by Rs [i] */ + + Int + n_row, n_col, /* A is n_row-by-n_row */ + n1 ; /* number of singletons */ + + /* for information only: */ + Int + tail_usage, /* amount of memory allocated in tail */ + /* head_usage is Numeric->ihead */ + init_usage, /* memory usage just after UMF_kernel_init */ + max_usage, /* peak memory usage (excludes internal and external */ + /* fragmentation in the tail) */ + ngarbage, /* number of garbage collections performed */ + nrealloc, /* number of reallocations performed */ + ncostly, /* number of costly reallocations performed */ + isize, /* size of integer pattern of L and U */ + nLentries, /* number of entries in L, excluding diagonal */ + nUentries, /* number of entries in U, including diagonal */ + /* Some entries may be numerically zero. */ + lnz, /* number of nonzero entries in L, excl. diagonal */ + all_lnz, /* lnz plus entries dropped from L */ + unz, /* number of nonzero entries in U, excl. diagonal */ + all_unz, /* unz plus entries dropped form U */ + maxfrsize ; /* largest actual front size */ + + Int maxnrows, maxncols ; /* not the same as Symbolic->maxnrows/cols* */ + +} NumericType ; + + + +/* -------------------------------------------------------------------------- */ +/* Element tuples for connecting elements together in a matrix */ +/* -------------------------------------------------------------------------- */ + +typedef struct /* Tuple */ +{ + /* The (e,f) tuples for the element lists */ + Int + e, /* element */ + f ; /* contribution to the row/col appears at this offset */ + +} Tuple ; + +#define TUPLES(t) MAX (4, (t) + 1) + +/* Col_degree is aliased with Cperm, and Row_degree with Rperm */ +#define NON_PIVOTAL_COL(col) (Col_degree [col] >= 0) +#define NON_PIVOTAL_ROW(row) (Row_degree [row] >= 0) + +/* -------------------------------------------------------------------------- */ +/* An element */ +/* -------------------------------------------------------------------------- */ + +typedef struct /* Element */ +{ + Int + + cdeg, /* external column degree + cdeg0 offset */ + rdeg, /* external row degree + rdeg0 offset */ + nrowsleft, /* number of rows remaining */ + ncolsleft, /* number of columns remaining */ + nrows, /* number of rows */ + ncols, /* number of columns */ + next ; /* for list link of sons, used during assembly only */ + + /* followed in memory by: + Int + col [0..ncols-1], column indices of this element + row [0..nrows-1] ; row indices of this element + Entry (suitably aligned, see macro below) + C [0...nrows-1, 0...ncols-1] ; + size of C is nrows*ncols Entry's + */ + +} Element ; + +/* macros for computing pointers to row/col indices, and contribution block: */ + +#define GET_ELEMENT_SIZE(nr,nc) \ +(UNITS (Element, 1) + UNITS (Int, (nc) + (nr)) + UNITS (Entry, (nc) * (nr))) + +#define DGET_ELEMENT_SIZE(nr,nc) \ +(DUNITS (Element, 1) + DUNITS (Int, (nc) + (nr)) + DUNITS (Entry, (nc) * (nr))) + +#define GET_ELEMENT_COLS(ep,p,Cols) { \ + ASSERT (p != (Unit *) NULL) ; \ + ASSERT (p >= Numeric->Memory + Numeric->itail) ; \ + ASSERT (p <= Numeric->Memory + Numeric->size) ; \ + ep = (Element *) p ; \ + p += UNITS (Element, 1) ; \ + Cols = (Int *) p ; \ +} + +#define GET_ELEMENT_PATTERN(ep,p,Cols,Rows,ncm) { \ + GET_ELEMENT_COLS (ep, p, Cols) ; \ + ncm = ep->ncols ; \ + Rows = Cols + ncm ; \ +} + +#define GET_ELEMENT(ep,p,Cols,Rows,ncm,nrm,C) { \ + GET_ELEMENT_PATTERN (ep, p, Cols, Rows, ncm) ; \ + nrm = ep->nrows ; \ + p += UNITS (Int, ncm + nrm) ; \ + C = (Entry *) p ; \ +} + +/* -------------------------------------------------------------------------- */ +/* Work data structure */ +/* -------------------------------------------------------------------------- */ + +/* + This data structure holds items needed only during factorization. + All of this is freed when UMFPACK_numeric completes. Note that some of + it is stored in the tail end of Numeric->S (namely, the Tuples and the + Elements). +*/ + +typedef struct /* WorkType */ +{ + + /* ---------------------------------------------------------------------- */ + /* information about each row and col of A */ + /* ---------------------------------------------------------------------- */ + + /* + Row_tuples: pointer to tuple list (alias with Numeric->Uip) + Row_tlen: number of tuples (alias with Numeric->Uilen) + Col_tuples: pointer to tuple list (alias with Numeric->Lip) + Col_tlen: number of tuples (alias with Numeric->Lilen) + Row_degree: degree of the row or column (alias Numeric->Rperm) + Col_degree: degree of the row or column (alias Numeric->Cperm) + + The Row_degree and Col_degree are MATLAB-style colmmd approximations, + are equal to the sum of the sizes of the elements (contribution blocks) + in each row and column. They are maintained when elements are created + and assembled. They are used only during the pivot row and column + search. They are not needed to represent the pattern of the remaining + matrix. + */ + + /* ---------------------------------------------------------------------- */ + /* information about each element */ + /* ---------------------------------------------------------------------- */ + + Int *E ; /* E [0 .. Work->elen-1] element "pointers" */ + /* (offsets in Numeric->Memory) */ + + /* ---------------------------------------------------------------------- */ + /* generic workspace */ + /* ---------------------------------------------------------------------- */ + + Entry *Wx, *Wy ; /* each of size maxnrows+1 */ + + Int /* Sizes: nn = MAX (n_row, n_col) */ + *Wp, /* nn+1 */ + *Wrp, /* n_col+1 */ + *Wm, /* maxnrows+1 */ + *Wio, /* maxncols+1 */ + *Woi, /* maxncols+1 */ + *Woo, /* MAX (maxnrows,maxncols)+1 */ + *Wrow, /* pointer to Fcols, Wio, or Woi */ + *NewRows, /* list of rows to scan */ + *NewCols ; /* list of cols to scan */ + + /* ---------------------------------------------------------------------- */ + + Int + *Lpattern, /* pattern of column of L, for one Lchain */ + *Upattern, /* pattern of row of U, for one Uchain */ + ulen, llen ; /* length of Upattern and Lpattern */ + + Int + *Diagonal_map, /* used for symmetric pivoting, of size nn+1 */ + *Diagonal_imap ;/* used for symmetric pivoting, of size nn+1 */ + + /* ---------------------------------------------------------------------- */ + + Int + n_row, n_col, /* matrix is n_row-by-n_col */ + nz, /* nonzeros in the elements for this matrix */ + n1, /* number of row and col singletons */ + elen, /* max possible number of elements */ + npiv, /* number of pivot rows and columns so far */ + ndiscard, /* number of discarded pivot columns */ + Wrpflag, + nel, /* elements in use are in the range 1..nel */ + noff_diagonal, + prior_element, + rdeg0, cdeg0, + rrdeg, ccdeg, + Candidates [MAX_CANDIDATES], /* current candidate pivot columns */ + nCandidates, /* number of candidates in Candidate set */ + ksuper, + firstsuper, + jsuper, + ncand, /* number of candidates (some not in Candidates[ ]) */ + nextcand, /* next candidate to place in Candidate search set */ + lo, + hi, + pivrow, /* current pivot row */ + pivcol, /* current pivot column */ + do_extend, /* true if the next pivot extends the current front */ + do_update, /* true if update should be applied */ + nforced, /* number of forced updates because of frontal growth */ + any_skip, + do_scan2row, + do_scan2col, + do_grow, + pivot_case, + frontid, /* id of current frontal matrix */ + nfr ; /* number of frontal matrices */ + + /* ---------------------------------------------------------------------- */ + /* For row-merge tree */ + /* ---------------------------------------------------------------------- */ + + Int + *Front_new1strow ; + + /* ---------------------------------------------------------------------- */ + /* current frontal matrix, F */ + /* ---------------------------------------------------------------------- */ + + Int Pivrow [MAXNB], + Pivcol [MAXNB] ; + + Entry + *Flublock, /* LU block, nb-by-nb */ + *Flblock, /* L block, fnr_curr-by-nb */ + *Fublock, /* U block, nb-by-fnc_curr, or U' fnc_curr-by-nb */ + *Fcblock ; /* C block, fnr_curr-by-fnc_curr */ + + Int + *Frows, /* Frows [0.. ]: row indices of F */ + + *Fcols, /* Fcols [0.. ]: column indices of F */ + + *Frpos, /* position of row indices in F, or -1 if not present */ + /* if Frows[i] == row, then Frpos[row] == i */ + + *Fcpos, /* position of col indices in F, or -1 if not present */ + /* if Fcols[j] == col, then */ + /* Fcpos[col] == j*Work->fnr_curr */ + + fnrows, /* number of rows in contribution block in F */ + fncols, /* number of columns in contribution block in F */ + fnr_curr, /* maximum # of rows in F (leading dimension) */ + fnc_curr, /* maximum # of columns in F */ + fcurr_size, /* current size of F */ + fnrows_max, /* max possible column-dimension (max # of rows) of F */ + fncols_max, /* max possible row-dimension (max # of columns) of F */ + nb, + fnpiv, /* number of pivots in F */ + fnzeros, /* number of explicit zero entries in LU block */ + fscan_row, /* where to start scanning rows of F in UMF_assemble */ + fscan_col, /* where to start scanning cols of F in UMF_assemble */ + fnrows_new, /* number of new row indices in F after pivot added */ + fncols_new, /* number of new col indices in F after pivot added */ + pivrow_in_front, /* true if current pivot row in Frows */ + pivcol_in_front ; /* true if current pivot column in Fcols */ + + /* ---------------------------------------------------------------------- + * Current frontal matrix + * ---------------------------------------------------------------------- + * The current frontal matrix is held as a single block of memory allocated + * from the "tail" end of Numeric->Memory. It is subdivided into four + * parts: an LU block, an L block, a U block, and a C block. + * + * Let k = fnpiv, r = fnrows, and c = fncols for the following discussion. + * Let dr = fnr_curr and dc = fnc_curr. Note that r <= dr and c <= dc. + * + * The LU block is of dimension nb-by-nb. The first k-by-k part holds the + * "diagonal" part of the LU factors for these k pivot rows and columns. + * The k pivot row and column indices in this part are Pivrow [0..k-1] and + * Pivcol [0..k-1], respectively. + * + * The L block is of dimension dr-by-nb. It holds the k pivot columns, + * except for the leading k-by-k part in the LU block. Only the leading + * r-by-k part is in use. + * + * The U block is of dimension dc-by-nb. It holds the k pivot rows, + * except for the leading k-by-k part in the LU block. It is stored in + * row-oriented form. Only the leading c-by-k part is in use. + * + * The C block is of dimension dr-by-dc. It holds the current contribution + * block. Only the leading r-by-c part is in use. The column indices in + * the C block are Fcols [0..c-1], and the row indices are Frows [0..r-1]. + * + * dr is always odd, to avoid bad cache behavior. + */ + +} WorkType ; + + +/* -------------------------------------------------------------------------- */ +/* Symbolic */ +/* -------------------------------------------------------------------------- */ + +/* + This is is constructed by UMFPACK_symbolic, and is needed by UMFPACK_numeric + to factor the matrix. +*/ + +typedef struct /* SymbolicType */ +{ + + double + num_mem_usage_est, /* estimated max Numeric->Memory size */ + num_mem_size_est, /* estimated final Numeric->Memory size */ + peak_sym_usage, /* peak Symbolic and SymbolicWork usage */ + sym, /* symmetry of pattern */ + dnum_mem_init_usage, /* min Numeric->Memory for UMF_kernel_init */ + amd_lunz, /* nz in LU for AMD, with symmetric pivoting */ + lunz_bound ; /* max nx in LU, for arbitrary row pivoting */ + + Int valid, /* set to SYMBOLIC_VALID, for validity check */ + max_nchains, + nchains, + *Chain_start, + *Chain_maxrows, + *Chain_maxcols, + maxnrows, /* largest number of rows in any front */ + maxncols, /* largest number of columns in any front */ + *Front_npivcol, /* Front_npivcol [j] = size of jth supercolumn*/ + *Front_1strow, /* first row index in front j */ + *Front_leftmostdesc, /* leftmost desc of front j */ + *Front_parent, /* super-column elimination tree */ + *Cperm_init, /* initial column ordering */ + *Rperm_init, /* initial row ordering */ + *Cdeg, *Rdeg, + *Esize, + dense_row_threshold, + n1, /* number of singletons */ + nempty, /* MIN (nempty_row, nempty_col) */ + *Diagonal_map, /* initial "diagonal" (after 2by2) */ + esize, /* size of Esize array */ + nfr, + n_row, n_col, /* matrix A is n_row-by-n_col */ + nz, /* nz of original matrix */ + nb, /* block size for BLAS 3 */ + num_mem_init_usage, /* min Numeric->Memory for UMF_kernel_init */ + nempty_row, nempty_col, + + strategy, + ordering, + fixQ, + prefer_diagonal, + nzaat, + nzdiag, + amd_dmax ; + +} SymbolicType ; + + +/* -------------------------------------------------------------------------- */ +/* for debugging only: */ +/* -------------------------------------------------------------------------- */ + +#include "umf_dump.h" + +/* -------------------------------------------------------------------------- */ +/* for statement coverage testing only: */ +/* -------------------------------------------------------------------------- */ + +#ifdef TESTING + +/* for testing integer overflow: */ +#ifdef TEST_FOR_INTEGER_OVERFLOW +#undef MAX_MARK +#define MAX_MARK(n) (3*(n)) +#endif + +/* for testing out-of-memory conditions: */ +#define UMF_TCOV_TEST +GLOBAL extern int umf_fail, umf_fail_lo, umf_fail_hi ; +GLOBAL extern int umf_realloc_fail, umf_realloc_lo, umf_realloc_hi ; + +/* for testing malloc count: */ +#define UMF_MALLOC_COUNT + +#endif + +#endif diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.c b/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.c @@ -0,0 +1,55 @@ +/* ========================================================================== */ +/* === UMF_is_permutation =================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Return TRUE if P is a r-permutation vector, FALSE otherwise */ +/* P [0..r-1] must be an r-permutation of 0..n-1 */ + +#include "umf_internal.h" + +GLOBAL Int UMF_is_permutation +( + const Int P [ ], /* permutation of size r */ + Int W [ ], /* workspace of size n */ + Int n, + Int r +) +{ + Int i, k ; + + if (!P) + { + /* if P is (Int *) NULL, this is the identity permutation */ + return (TRUE) ; + } + + ASSERT (W != (Int *) NULL) ; + + for (i = 0 ; i < n ; i++) + { + W [i] = FALSE ; + } + for (k = 0 ; k < r ; k++) + { + i = P [k] ; + DEBUG5 (("k "ID" i "ID"\n", k, i)) ; + if (i < 0 || i >= n) + { + DEBUG0 (("i out of range "ID" "ID"\n", i, n)) ; + return (FALSE) ; + } + if (W [i]) + { + DEBUG0 (("i duplicate "ID"\n", i)) ; + return (FALSE) ; + } + W [i] = TRUE ; + } + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.h b/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_is_permutation.h @@ -0,0 +1,13 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_is_permutation +( + const Int P [ ], + Int W [ ], + Int n, + Int r +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.c b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.c @@ -0,0 +1,299 @@ +/* ========================================================================== */ +/* === UMF_kernel =========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Primary factorization routine. Called by UMFPACK_numeric. + Returns: + UMFPACK_OK if successful, + UMFPACK_ERROR_out_of_memory if out of memory, or + UMFPACK_ERROR_different_pattern if pattern of matrix (Ap and/or Ai) + has changed since the call to UMFPACK_*symbolic. +*/ + +#include "umf_internal.h" +#include "umf_kernel_init.h" +#include "umf_init_front.h" +#include "umf_start_front.h" +#include "umf_assemble.h" +#include "umf_scale_column.h" +#include "umf_local_search.h" +#include "umf_create_element.h" +#include "umf_extend_front.h" +#include "umf_blas3_update.h" +#include "umf_store_lu.h" +#include "umf_kernel_wrapup.h" + +/* perform an action, and return if out of memory */ +#define DO(action) { if (! (action)) { return (UMFPACK_ERROR_out_of_memory) ; }} + +GLOBAL Int UMF_kernel +( + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int j, f1, f2, chain, nchains, *Chain_start, status, fixQ, evaporate, + *Front_npivcol, jmax, nb, drop ; + + /* ---------------------------------------------------------------------- */ + /* initialize memory space and load the matrix. Optionally scale. */ + /* ---------------------------------------------------------------------- */ + + if (!UMF_kernel_init (Ap, Ai, Ax, +#ifdef COMPLEX + Az, +#endif + Numeric, Work, Symbolic)) + { + /* UMF_kernel_init is guaranteed to succeed, since UMFPACK_numeric */ + /* either allocates enough space or if not, UMF_kernel does not get */ + /* called. So running out of memory here is a fatal error, and means */ + /* that the user changed Ap and/or Ai since the call to */ + /* UMFPACK_*symbolic. */ + DEBUGm4 (("kernel init failed\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + + /* ---------------------------------------------------------------------- */ + /* get the symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + nchains = Symbolic->nchains ; + Chain_start = Symbolic->Chain_start ; + Front_npivcol = Symbolic->Front_npivcol ; + nb = Symbolic->nb ; + fixQ = Symbolic->fixQ ; + drop = Numeric->droptol > 0.0 ; + +#ifndef NDEBUG + for (chain = 0 ; chain < nchains ; chain++) + { + Int i ; + f1 = Chain_start [chain] ; + f2 = Chain_start [chain+1] - 1 ; + DEBUG1 (("\nCHain: "ID" start "ID" end "ID"\n", chain, f1, f2)) ; + for (i = f1 ; i <= f2 ; i++) + { + DEBUG1 (("Front "ID", npivcol "ID"\n", i, Front_npivcol [i])) ; + } + } +#endif + + /* ---------------------------------------------------------------------- */ + /* factorize each chain of frontal matrices */ + /* ---------------------------------------------------------------------- */ + + for (chain = 0 ; chain < nchains ; chain++) + { + f1 = Chain_start [chain] ; + f2 = Chain_start [chain+1] - 1 ; + + /* ------------------------------------------------------------------ */ + /* get the initial frontal matrix size for this chain */ + /* ------------------------------------------------------------------ */ + + DO (UMF_start_front (chain, Numeric, Work, Symbolic)) ; + + /* ------------------------------------------------------------------ */ + /* factorize each front in the chain */ + /* ------------------------------------------------------------------ */ + + for (Work->frontid = f1 ; Work->frontid <= f2 ; Work->frontid++) + { + + /* -------------------------------------------------------------- */ + /* Initialize the pivot column candidate set */ + /* -------------------------------------------------------------- */ + + Work->ncand = Front_npivcol [Work->frontid] ; + Work->lo = Work->nextcand ; + Work->hi = Work->nextcand + Work->ncand - 1 ; + jmax = MIN (MAX_CANDIDATES, Work->ncand) ; + DEBUGm1 ((">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Starting front " + ID", npivcol: "ID"\n", Work->frontid, Work->ncand)) ; + if (fixQ) + { + /* do not modify the column order */ + jmax = 1 ; + } + DEBUGm1 (("Initial candidates: ")) ; + for (j = 0 ; j < jmax ; j++) + { + DEBUGm1 ((" "ID, Work->nextcand)) ; + ASSERT (Work->nextcand <= Work->hi) ; + Work->Candidates [j] = Work->nextcand++ ; + } + Work->nCandidates = jmax ; + DEBUGm1 (("\n")) ; + + /* -------------------------------------------------------------- */ + /* Assemble and factorize the current frontal matrix */ + /* -------------------------------------------------------------- */ + + while (Work->ncand > 0) + { + + /* ---------------------------------------------------------- */ + /* get the pivot row and column */ + /* ---------------------------------------------------------- */ + + status = UMF_local_search (Numeric, Work, Symbolic) ; + if (status == UMFPACK_ERROR_different_pattern) + { + /* :: pattern change detected in umf_local_search :: */ + /* input matrix has changed since umfpack_*symbolic */ + DEBUGm4 (("local search failed\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + if (status == UMFPACK_WARNING_singular_matrix) + { + /* no pivot found, discard and try again */ + continue ; + } + + /* ---------------------------------------------------------- */ + /* update if front not extended or too many zeros in L,U */ + /* ---------------------------------------------------------- */ + + if (Work->do_update) + { + UMF_blas3_update (Work) ; + if (drop) + { + DO (UMF_store_lu_drop (Numeric, Work)) ; + } + else + { + DO (UMF_store_lu (Numeric, Work)) ; + } + } + + /* ---------------------------------------------------------- */ + /* extend the frontal matrix, or start a new one */ + /* ---------------------------------------------------------- */ + + if (Work->do_extend) + { + /* extend the current front */ + DO (UMF_extend_front (Numeric, Work)) ; + } + else + { + /* finish the current front (if any) and start a new one */ + DO (UMF_create_element (Numeric, Work, Symbolic)) ; + DO (UMF_init_front (Numeric, Work)) ; + } + + /* ---------------------------------------------------------- */ + /* Numerical & symbolic assembly into current frontal matrix */ + /* ---------------------------------------------------------- */ + + if (fixQ) + { + UMF_assemble_fixq (Numeric, Work) ; + } + else + { + UMF_assemble (Numeric, Work) ; + } + + /* ---------------------------------------------------------- */ + /* scale the pivot column */ + /* ---------------------------------------------------------- */ + + UMF_scale_column (Numeric, Work) ; + + /* ---------------------------------------------------------- */ + /* Numerical update if enough pivots accumulated */ + /* ---------------------------------------------------------- */ + + evaporate = Work->fnrows == 0 || Work->fncols == 0 ; + if (Work->fnpiv >= nb || evaporate) + { + UMF_blas3_update (Work) ; + if (drop) + { + DO (UMF_store_lu_drop (Numeric, Work)) ; + } + else + { + DO (UMF_store_lu (Numeric, Work)) ; + } + + } + + Work->pivrow_in_front = FALSE ; + Work->pivcol_in_front = FALSE ; + + /* ---------------------------------------------------------- */ + /* If front is empty, evaporate it */ + /* ---------------------------------------------------------- */ + + if (evaporate) + { + /* This does not create an element, just evaporates it. + * It ensures that a front is not 0-by-c or r-by-0. No + * memory is allocated, so it is guaranteed to succeed. */ + (void) UMF_create_element (Numeric, Work, Symbolic) ; + Work->fnrows = 0 ; + Work->fncols = 0 ; + } + } + } + + /* ------------------------------------------------------------------ + * Wrapup the current frontal matrix. This is the last in a chain + * in the column elimination tree. The next frontal matrix + * cannot overlap with the current one, which will be its sibling + * in the column etree. + * ------------------------------------------------------------------ */ + + UMF_blas3_update (Work) ; + if (drop) + { + DO (UMF_store_lu_drop (Numeric, Work)) ; + } + else + { + DO (UMF_store_lu (Numeric, Work)) ; + } + Work->fnrows_new = Work->fnrows ; + Work->fncols_new = Work->fncols ; + DO (UMF_create_element (Numeric, Work, Symbolic)) ; + + /* ------------------------------------------------------------------ */ + /* current front is now empty */ + /* ------------------------------------------------------------------ */ + + Work->fnrows = 0 ; + Work->fncols = 0 ; + } + + /* ---------------------------------------------------------------------- */ + /* end the last Lchain and Uchain and finalize the LU factors */ + /* ---------------------------------------------------------------------- */ + + UMF_kernel_wrapup (Numeric, Symbolic, Work) ; + + /* note that the matrix may be singular (this is OK) */ + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.h b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel.h @@ -0,0 +1,18 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_kernel +( + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.c b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.c @@ -0,0 +1,1056 @@ +/* ========================================================================== */ +/* === UMF_kernel_init ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Initialize the kernel: scale the matrix, load the initial elements, and + build the tuple lists. + + Returns TRUE if successful, FALSE if out of memory or if the pattern has + changed since UMFPACK_*symbolic. UMFPACK_numeric allocates at least enough + space for UMF_kernel_init to succeed; otherwise it does not call + UMF_kernel_init. So an out-of-memory condition means that the pattern must + have gotten larger. +*/ + +#include "umf_internal.h" +#include "umf_tuple_lengths.h" +#include "umf_build_tuples.h" +#include "umf_mem_init_memoryspace.h" +#include "umf_mem_alloc_element.h" +#include "umf_mem_alloc_head_block.h" +#include "umf_mem_alloc_tail_block.h" +#include "umf_mem_free_tail_block.h" +#include "umf_scale.h" + +/* ========================================================================== */ +/* === packsp =============================================================== */ +/* ========================================================================== */ + +/* remove zero or small entries from a column of L or a row of U */ + +PRIVATE Int packsp /* returns new value of pnew */ +( + Int pnew, /* index into Memory of next free space */ + Int *p_p, /* ptr to index of old pattern in Memory on input, + new pattern on output */ + Int *p_len, /* ptr to length of old pattern on input, + new pattern on output */ + Int drop, /* TRUE if small nonzero entries are to be dropped */ + double droptol, /* the drop tolerance */ + Unit *Memory /* contains the sparse vector on input and output */ +) +{ + Entry x ; + double s ; + Entry *Bx, *Bx2 ; + Int p, i, len, len_new, *Bi, *Bi2 ; + + /* get the pointers to the sparse vector, and its length */ + p = *p_p ; + len = *p_len ; + Bi = (Int *) (Memory + p) ; p += UNITS (Int, len) ; + Bx = (Entry *) (Memory + p) ; p += UNITS (Entry, len) ; + DEBUGm4 ((" p "ID" len "ID" pnew "ID"\n", p, len, pnew)) ; + + /* the vector resides in Bi [0..len-1] and Bx [0..len-1] */ + + /* first, compact the vector in place */ + len_new = 0 ; + for (p = 0 ; p < len ; p++) + { + i = Bi [p] ; + x = Bx [p] ; + DEBUGm4 ((" old vector: i "ID" value: ", i)) ; + EDEBUGk (-4, x) ; + DEBUGm4 (("\n")) ; + ASSERT (i >= 0) ; + /* skip if zero or below drop tolerance */ + if (IS_ZERO (x)) continue ; + if (drop) + { + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + } + /* store the value back into the vector */ + if (len_new != p) + { + Bi [len_new] = i ; + Bx [len_new] = x ; + } + len_new++ ; + } + ASSERT (len_new <= len) ; + + /* the vector is now in Bi [0..len_new-1] and Bx [0..len_new-1] */ + +#ifndef NDEBUG + for (p = 0 ; p < len_new ; p++) + { + DEBUGm4 ((" new vector: i "ID" value: ", Bi [p])) ; + EDEBUGk (-4, Bx [p]) ; + DEBUGm4 (("\n")) ; + ASSERT (Bi [p] >= 0) ; + } +#endif + + /* allocate new space for the compacted vector */ + *p_p = pnew ; + *p_len = len_new ; + Bi2 = (Int *) (Memory + pnew) ; pnew += UNITS (Int, len_new) ; + Bx2 = (Entry *) (Memory + pnew) ; pnew += UNITS (Entry, len_new) ; + DEBUGm4 ((" pnew "ID" len_new "ID"\n", pnew, len_new)) ; + + /* shift the vector upwards, into its new space */ + for (p = 0 ; p < len_new ; p++) + { + Bi2 [p] = Bi [p] ; + } + for (p = 0 ; p < len_new ; p++) + { + Bx2 [p] = Bx [p] ; + } + +#ifndef NDEBUG + for (p = 0 ; p < len_new ; p++) + { + DEBUGm4 ((" packed vec: i "ID" value: ", Bi2 [p])) ; + EDEBUGk (-4, Bx2 [p]) ; + DEBUGm4 (("\n")) ; + ASSERT (Bi2 [p] >= 0) ; + } +#endif + + /* return the pointer to the space just after the new vector */ + return (pnew) ; +} + + +/* ========================================================================== */ +/* === UMF_kernel_init ====================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMF_kernel_init +( + const Int Ap [ ], /* user's input matrix (not modified) */ + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry x, pivot_value ; + double unused = 0, rsmin, rsmax, rs, droptol ; + Entry *D, *C, *Lval, **Rpx ; + double *Rs ; + Int row, k, oldcol, size, e, p1, p2, p, nz, *Rows, *Cols, *E, i, *Upos, + *Lpos, n_row, n_col, *Wp, *Cperm_init, *Frpos, *Fcpos, *Row_degree, nn, + *Row_tlen, *Col_degree, *Col_tlen, oldrow, newrow, ilast, *Wrp, + *Rperm_init, col, n_inner, prefer_diagonal, *Diagonal_map, nempty, + *Diagonal_imap, fixQ, rdeg, cdeg, nempty_col, *Esize, esize, pnew, + *Lip, *Uip, *Lilen, *Uilen, llen, pa, *Cdeg, *Rdeg, n1, clen, do_scale, + lnz, unz, lip, uip, k1, *Rperm, *Cperm, pivcol, *Li, lilen, drop, + **Rpi, nempty_row, dense_row_threshold, empty_elements, rpi, rpx ; + Element *ep ; + Unit *Memory ; +#ifdef COMPLEX + Int split = SPLIT (Az) ; +#endif +#ifndef NRECIPROCAL + Int do_recip = FALSE ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + DEBUG0 (("KERNEL INIT\n")) ; + + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + nempty_col = Symbolic->nempty_col ; + nempty_row = Symbolic->nempty_row ; + nempty = MIN (nempty_row, nempty_col) ; + ASSERT (n_row > 0 && n_col > 0) ; + Cperm_init = Symbolic->Cperm_init ; + Rperm_init = Symbolic->Rperm_init ; + Cdeg = Symbolic->Cdeg ; + Rdeg = Symbolic->Rdeg ; + n1 = Symbolic->n1 ; + dense_row_threshold = Symbolic->dense_row_threshold ; + DEBUG0 (("Singletons: "ID"\n", n1)) ; + Work->nforced = 0 ; + Work->ndiscard = 0 ; + Work->noff_diagonal = 0 ; + + nz = Ap [n_col] ; + if (nz < 0 || Ap [0] != 0 || nz != Symbolic->nz) + { + DEBUGm4 (("nz or Ap [0] bad\n")) ; + return (FALSE) ; /* pattern changed */ + } + + prefer_diagonal = Symbolic->prefer_diagonal ; + Diagonal_map = Work->Diagonal_map ; + Diagonal_imap = Work->Diagonal_imap ; + + /* ---------------------------------------------------------------------- */ + /* initialize the Numeric->Memory space for LU, elements, and tuples */ + /* ---------------------------------------------------------------------- */ + + UMF_mem_init_memoryspace (Numeric) ; + DEBUG1 (("Kernel init head usage, before allocs: "ID"\n", Numeric->ihead)) ; + + /* ---------------------------------------------------------------------- */ + /* initialize the Work and Numeric objects */ + /* ---------------------------------------------------------------------- */ + + /* current front is empty */ + Work->fnpiv = 0 ; + Work->fncols = 0 ; + Work->fnrows = 0 ; + Work->fncols_max = 0 ; + Work->fnrows_max = 0 ; + Work->fnzeros = 0 ; + Work->fcurr_size = 0 ; + Work->fnr_curr = 0 ; + Work->fnc_curr = 0 ; + + Work->nz = nz ; + Work->prior_element = EMPTY ; + Work->ulen = 0 ; + Work->llen = 0 ; + Work->npiv = n1 ; + Work->frontid = 0 ; + Work->nextcand = n1 ; + + Memory = Numeric->Memory ; + Rperm = Numeric->Rperm ; + Cperm = Numeric->Cperm ; + Row_degree = Numeric->Rperm ; + Col_degree = Numeric->Cperm ; + /* Row_tuples = Numeric->Uip ; not needed */ + Row_tlen = Numeric->Uilen ; + /* Col_tuples = Numeric->Lip ; not needed */ + Col_tlen = Numeric->Lilen ; + + Lip = Numeric->Lip ; + Uip = Numeric->Uip ; + Lilen = Numeric->Lilen ; + Uilen = Numeric->Uilen ; + + Frpos = Work->Frpos ; + Fcpos = Work->Fcpos ; + Wp = Work->Wp ; + Wrp = Work->Wrp ; + + D = Numeric->D ; + Upos = Numeric->Upos ; + Lpos = Numeric->Lpos ; + for (k = 0 ; k < n_inner ; k++) + { + CLEAR (D [k]) ; + } + + Rs = Numeric->Rs ; + + for (row = 0 ; row <= n_row ; row++) + { + Lpos [row] = EMPTY ; + /* Row_tuples [row] = 0 ; set in UMF_build_tuples */ + /* Row_degree [row] = 0 ; initialized below */ + Row_tlen [row] = 0 ; + /* Frpos [row] = EMPTY ; do this later */ + } + + for (col = 0 ; col <= n_col ; col++) + { + Upos [col] = EMPTY ; + /* Col_tuples [col] = 0 ; set in UMF_build_tuples */ + /* Col_degree [col] = 0 ; initialized below */ + Col_tlen [col] = 0 ; + Fcpos [col] = EMPTY ; + Wrp [col] = 0 ; + } + Work->Wrpflag = 1 ; + + /* When cleared, Wp [0..nn] is < 0 */ + for (i = 0 ; i <= nn ; i++) + { + Wp [i] = EMPTY ; + } + /* In col search, Wp [row] is set to a position, which is >= 0. */ + + /* When cleared, Wrp [0..n_col] is < Wrpflag */ + /* In row search, Wrp [col] is set to Wrpflag. */ + + /* no need to initialize Wm, Wio, Woi, and Woo */ + + /* clear the external degree counters */ + Work->cdeg0 = 1 ; + Work->rdeg0 = 1 ; + + fixQ = Symbolic->fixQ ; + + E = Work->E ; + + Numeric->n_row = n_row ; + Numeric->n_col = n_col ; + Numeric->npiv = 0 ; + Numeric->nnzpiv = 0 ; + Numeric->min_udiag = 0.0 ; + Numeric->max_udiag = 0.0 ; + Numeric->rcond = 0.0 ; + Numeric->isize = 0 ; + Numeric->nLentries = 0 ; + Numeric->nUentries = 0 ; + Numeric->lnz = 0 ; + Numeric->unz = 0 ; + Numeric->all_lnz = 0 ; + Numeric->all_unz = 0 ; + Numeric->maxfrsize = 0 ; + Numeric->maxnrows = 0 ; + Numeric->maxncols = 0 ; + Numeric->flops = 0. ; + Numeric->n1 = n1 ; + droptol = Numeric->droptol ; + drop = (droptol > 0) ; + + /* ---------------------------------------------------------------------- */ + /* compute the scale factors, if requested, and check the input matrix */ + /* ---------------------------------------------------------------------- */ + + /* UMFPACK_SCALE_SUM: Rs [i] = sum of the absolute values in row i. + * UMFPACK_SCALE_MAX: Rs [i] = max of the absolute values in row i. + * + * If A is complex, an approximate abs is used (|xreal| + |ximag|). + * + * If min (Rs [0..n_row]) >= RECIPROCAL_TOLERANCE, then the scale + * factors are inverted, and the rows of A are multiplied by the scale + * factors. Otherwise, the rows are divided by the scale factors. If + * NRECIPROCAL is defined, then the rows are always divided by the scale + * factors. + * + * For MATLAB (either built-in routine or mexFunction), or for gcc, + * the rows are always divided by the scale factors. + */ + + do_scale = (Numeric->scale != UMFPACK_SCALE_NONE) ; + + if (do_scale) + { + int do_max = Numeric->scale == UMFPACK_SCALE_MAX ; + for (row = 0 ; row < n_row ; row++) + { + Rs [row] = 0.0 ; + } + for (col = 0 ; col < n_col ; col++) + { + ilast = EMPTY ; + p1 = Ap [col] ; + p2 = Ap [col+1] ; + if (p1 > p2) + { + /* invalid matrix */ + DEBUGm4 (("invalid matrix (Ap)\n")) ; + return (FALSE) ; + } + for (p = p1 ; p < p2 ; p++) + { + Entry aij ; + double value ; + row = Ai [p] ; + if (row <= ilast || row >= n_row) + { + /* invalid matrix, columns must be sorted, no duplicates */ + DEBUGm4 (("invalid matrix (Ai)\n")) ; + return (FALSE) ; + } + ASSIGN (aij, Ax, Az, p, split) ; + APPROX_ABS (value, aij) ; + rs = Rs [row] ; + if (!SCALAR_IS_NAN (rs)) + { + if (SCALAR_IS_NAN (value)) + { + /* if any entry in the row is NaN, then the scale factor + * is NaN too (for now) and then set to 1.0 below */ + Rs [row] = value ; + } + else if (do_max) + { + Rs [row] = MAX (rs, value) ; + } + else + { + Rs [row] += value ; + } + } + DEBUG4 (("i "ID" j "ID" value %g, Rs[i]: %g\n", + row, col, value, Rs[row])) ; + ilast = row ; + } + } + DEBUG2 (("Rs[0] = %30.20e\n", Rs [0])) ; + for (row = 0 ; row < n_row ; row++) + { + rs = Rs [row] ; + if (SCALAR_IS_ZERO (rs) || SCALAR_IS_NAN (rs)) + { + /* don't scale a completely zero row, or one with NaN's */ + Rs [row] = 1.0 ; + } + } + rsmin = Rs [0] ; + rsmax = Rs [0] ; + for (row = 0 ; row < n_row ; row++) + { + DEBUG2 (("sum %30.20e ", Rs [row])) ; + rsmin = MIN (rsmin, Rs [row]) ; + rsmax = MAX (rsmax, Rs [row]) ; + DEBUG2 (("Rs["ID"] = %30.20e\n", row, Rs [row])) ; + } +#ifndef NRECIPROCAL + /* multiply by the reciprocal if Rs is not too small */ + do_recip = (rsmin >= RECIPROCAL_TOLERANCE) ; + if (do_recip) + { + /* invert the scale factors */ + for (row = 0 ; row < n_row ; row++) + { + Rs [row] = 1.0 / Rs [row] ; + } + } +#endif + } + else + { + /* no scaling, rsmin and rsmax not computed */ + rsmin = -1 ; + rsmax = -1 ; +#ifndef NRECIPROCAL + do_recip = FALSE ; +#endif + /* check the input matrix */ + if (!AMD_valid (n_row, n_col, Ap, Ai)) + { + /* matrix is invalid */ + return (FALSE) ; + } + } + + Numeric->rsmin = rsmin ; + Numeric->rsmax = rsmax ; +#ifndef NRECIPROCAL + Numeric->do_recip = do_recip ; +#else + Numeric->do_recip = FALSE ; +#endif + + /* ---------------------------------------------------------------------- */ + /* construct the inverse row Rperm_init permutation (use Frpos as temp) */ + /* ---------------------------------------------------------------------- */ + + DEBUG3 (("\n\n===================LOAD_MATRIX:\n")) ; + + for (newrow = 0 ; newrow < n_row ; newrow++) + { + oldrow = Rperm_init [newrow] ; + ASSERT (oldrow >= 0 && oldrow < n_row) ; + Frpos [oldrow] = newrow ; + } + + /* ---------------------------------------------------------------------- */ + /* construct the diagonal imap if doing symmetric pivoting */ + /* ---------------------------------------------------------------------- */ + + if (prefer_diagonal) + { + ASSERT (n_row == n_col) ; + ASSERT (nempty_col == Symbolic->nempty_row) ; + ASSERT (nempty_col == nempty) ; + for (i = 0 ; i < nn ; i++) + { + Diagonal_map [i] = EMPTY ; + Diagonal_imap [i] = EMPTY ; + } + for (k = n1 ; k < nn - nempty ; k++) + { + newrow = Symbolic->Diagonal_map [k] ; + Diagonal_map [k] = newrow ; + Diagonal_imap [newrow] = k ; + } + } + + /* ---------------------------------------------------------------------- */ + /* allocate O (n_row) workspace at the tail end of Memory */ + /* ---------------------------------------------------------------------- */ + + rpi = UMF_mem_alloc_tail_block (Numeric, UNITS (Int *, n_row+1)) ; + rpx = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry *, n_row+1)) ; + if (!rpi || !rpx) + { + /* :: pattern change (out of memory for Rpx, Rpx) :: */ + /* out of memory, which can only mean that the pattern has changed */ + return (FALSE) ; /* pattern changed */ + } + Rpi = (Int **) (Memory + rpx) ; + Rpx = (Entry **) (Memory + rpi) ; + + /* ---------------------------------------------------------------------- */ + /* allocate the LU factors for the columns of the singletons */ + /* ---------------------------------------------------------------------- */ + + DEBUG1 (("Allocating singletons:\n")) ; + for (k = 0 ; k < n1 ; k++) + { + lnz = Cdeg [k] - 1 ; + unz = Rdeg [k] - 1 ; + + DEBUG1 (("Singleton k "ID" pivrow "ID" pivcol "ID" cdeg "ID" rdeg " + ID"\n", k, Rperm_init [k], Cperm_init [k], Cdeg [k], Rdeg [k])) ; + ASSERT (unz >= 0 && lnz >= 0 && (lnz == 0 || unz == 0)) ; + DEBUG1 ((" lnz "ID" unz "ID"\n", lnz, unz)) ; + + size = UNITS (Int, lnz) + UNITS (Entry, lnz) + + UNITS (Int, unz) + UNITS (Entry, unz) ; + p = UMF_mem_alloc_head_block (Numeric, size) ; + DEBUG1 (("Kernel init head usage: "ID"\n", Numeric->ihead)) ; + if (!p) + { + /* :: pattern change (out of memory for singletons) :: */ + DEBUG0 (("Pattern has gotten larger - kernel init failed\n")) ; + return (FALSE) ; /* pattern changed */ + } + + Numeric->all_lnz += lnz ; + Numeric->all_unz += unz ; + + /* allocate the column of L */ + lip = p ; + p += UNITS (Int, lnz) ; + p += UNITS (Entry, lnz) ; + + /* allocate the row of U */ + uip = p ; + Rpi [k] = (Int *) (Memory + p) ; + p += UNITS (Int, unz) ; + Rpx [k] = (Entry *) (Memory + p) ; + /* p += UNITS (Entry, unz) ; (not needed) */ + + /* a single column of L (no Lchains) */ + Lip [k] = lip ; + Lilen [k] = lnz ; + + /* a single row of L (no Uchains) */ + Uip [k] = uip ; + Uilen [k] = unz ; + + Wp [k] = unz ; + + /* save row and column inverse permutation */ + k1 = ONES_COMPLEMENT (k) ; + Rperm [k] = k1 ; /* aliased with Row_degree */ + Cperm [k] = k1 ; /* aliased with Col_degree */ + } + + /* ---------------------------------------------------------------------- */ + /* current frontal matrix is empty */ + /* ---------------------------------------------------------------------- */ + + e = 0 ; + E [e] = 0 ; + Work->Flublock = (Entry *) NULL ; + Work->Flblock = (Entry *) NULL ; + Work->Fublock = (Entry *) NULL ; + Work->Fcblock = (Entry *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* allocate the column elements */ + /* ---------------------------------------------------------------------- */ + + Esize = Symbolic->Esize ; + empty_elements = FALSE ; + for (k = n1 ; k < n_col - nempty_col ; k++) + { + e = k - n1 + 1 ; + ASSERT (e < Work->elen) ; + esize = Esize ? Esize [k-n1] : Cdeg [k] ; + if (esize > 0) + { + /* allocate an element for this column */ + E [e] = UMF_mem_alloc_element (Numeric, esize, 1, &Rows, &Cols, &C, + &size, &ep) ; + if (E [e] <= 0) + { + /* :: pattern change (out of memory for column elements) :: */ + return (FALSE) ; /* pattern has changed */ + } + Cols [0] = k ; + DEBUG0 (("Got column element e "ID" esize "ID"\n", e, esize)) ; + } + else + { + /* all rows in this column are dense, or empty */ + E [e] = 0 ; + empty_elements = TRUE ; + DEBUG0 (("column element e is empty "ID"\n", e)) ; + } + } + DEBUG0 (("e "ID" n_col "ID" nempty_col "ID" n1 "ID"\n", e, n_col, + nempty_col, n1)) ; + ASSERT (e == n_col - nempty_col - n1) ; + + /* ---------------------------------------------------------------------- */ + /* allocate the row elements for dense rows of A (if any) */ + /* ---------------------------------------------------------------------- */ + + if (Esize) + { + for (k = n1 ; k < n_row - nempty_row ; k++) + { + rdeg = Rdeg [k] ; + if (rdeg > dense_row_threshold) + { + /* allocate an element for this dense row */ + e++ ; + ASSERT (e < Work->elen) ; + E [e] = UMF_mem_alloc_element (Numeric, 1, rdeg, &Rows, &Cols, + &C, &size, &ep) ; + if (E [e] <= 0) + { + /* :: pattern change (out of memory for row elements) :: */ + return (FALSE) ; /* pattern has changed */ + } + Rows [0] = k ; + Rpi [k] = Cols ; + Rpx [k] = C ; + Wp [k] = rdeg ; + DEBUG0 (("Got row element e "ID" rdeg "ID"\n", e, rdeg)) ; + } + } + } + + /* elements are currently in the range 0 to e */ + Work->nel = e ; + + /* ---------------------------------------------------------------------- */ + /* create the first n1 columns of L and U */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + pivcol = Cperm_init [k] ; + p2 = Ap [pivcol+1] ; + + /* get the kth column of L */ + p = Lip [k] ; + Li = (Int *) (Memory + p) ; + lilen = Lilen [k] ; + p += UNITS (Int, lilen) ; + Lval = (Entry *) (Memory + p) ; + + llen = 0 ; + + for (pa = Ap [pivcol] ; pa < p2 ; pa++) + { + oldrow = Ai [pa] ; + newrow = Frpos [oldrow] ; + ASSIGN (x, Ax, Az, pa, split) ; + + /* scale the value using the scale factors, Rs */ + if (do_scale) + { +#ifndef NRECIPROCAL + if (do_recip) + { + SCALE (x, Rs [oldrow]) ; + } + else +#endif + { + SCALE_DIV (x, Rs [oldrow]) ; + } + } + + if (newrow == k) + { + /* this is the pivot entry itself */ + ASSERT (oldrow == Rperm_init [k]) ; + D [k] = x ; + } + else if (newrow < k) + { + /* this entry goes in a row of U */ + DEBUG1 (("Singleton row of U: k "ID" newrow "ID"\n", + k, newrow)) ; + if (--(Wp [newrow]) < 0) + { + /* :: pattern change (singleton row too long) :: */ + DEBUGm4 (("bad U singleton row (too long)\n")) ; + return (FALSE) ; /* pattern changed */ + } + *(Rpi [newrow]++) = k ; + *(Rpx [newrow]++) = x ; + } + else + { + /* this entry goes in a column of L */ + DEBUG1 (("Singleton col of L: k "ID" newrow "ID"\n", + k, newrow)) ; + if (llen >= lilen) + { + DEBUGm4 (("bad L singleton col (too long)\n")) ; + return (FALSE) ; /* pattern changed */ + } + Li [llen] = newrow ; + Lval [llen] = x ; + llen++ ; + } + } + + if (llen != lilen) + { + /* :: pattern change (singleton column too long) :: */ + DEBUGm4 (("bad L singleton col (too short)\n")) ; + return (FALSE) ; /* pattern changed */ + } + + /* scale the column of L */ + if (llen > 0) + { + pivot_value = D [k] ; + UMF_scale (llen, pivot_value, Lval) ; + } + + } + + /* ---------------------------------------------------------------------- */ + /* allocate the elements and copy the columns of A */ + /* ---------------------------------------------------------------------- */ + + /* also apply the row and column pre-ordering. */ + for (k = n1 ; k < n_col ; k++) + { + /* The newcol is k, which is what the name of the column is in the + * UMFPACK kernel. The user's name for the column is oldcol. */ + oldcol = Cperm_init [k] ; + + ASSERT (oldcol >= 0 && oldcol < n_col) ; + + p2 = Ap [oldcol+1] ; + + cdeg = Cdeg [k] ; + ASSERT (cdeg >= 0) ; + ASSERT (IMPLIES ( + (Symbolic->ordering != UMFPACK_ORDERING_GIVEN) && n1 > 0, + cdeg > 1 || cdeg == 0)) ; + + /* if fixQ: set Col_degree to 0 for the NON_PIVOTAL_COL macro */ + Col_degree [k] = fixQ ? 0 : cdeg ; + + /* get the element for this column (if any) */ + e = k - n1 + 1 ; + if (k < n_col - nempty_col) + { + esize = Esize ? Esize [k-n1] : cdeg ; + if (E [e]) + { + Int ncols, nrows ; + Unit *pp ; + pp = Memory + E [e] ; + GET_ELEMENT (ep, pp, Cols, Rows, ncols, nrows, C) ; + ASSERT (ncols == 1) ; + ASSERT (nrows == esize) ; + ASSERT (Cols [0] == k) ; + } + } + else + { + ASSERT (cdeg == 0) ; + esize = 0 ; + } + + clen = 0 ; + + for (pa = Ap [oldcol] ; pa < p2 ; pa++) + { + oldrow = Ai [pa] ; + newrow = Frpos [oldrow] ; + ASSIGN (x, Ax, Az, pa, split) ; + + /* scale the value using the scale factors, Rs */ + if (do_scale) + { +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the reciprocal */ + SCALE (x, Rs [oldrow]) ; + } + else +#endif + { + /* divide instead */ + SCALE_DIV (x, Rs [oldrow]) ; + } + } + + rdeg = Rdeg [newrow] ; + if (newrow < n1 || rdeg > dense_row_threshold) + { + /* this entry goes in a row of U or into a dense row */ + DEBUG1 (("Singleton/dense row of U: k "ID" newrow "ID"\n", + k, newrow)) ; + if (--(Wp [newrow]) < 0) + { + DEBUGm4 (("bad row of U or A (too long)\n")) ; + return (FALSE) ; /* pattern changed */ + } + *(Rpi [newrow]++) = k ; + *(Rpx [newrow]++) = x ; + } + else + { + /* this entry goes in an initial element */ + DEBUG1 (("In element k "ID" e "ID" newrow "ID"\n", + k, e, newrow)) ; + if (clen >= esize) + { + DEBUGm4 (("bad A column (too long)\n")) ; + return (FALSE) ; /* pattern changed */ + } + ASSERT (E [e]) ; + ASSERT (k < n_col - nempty_col) ; + Rows [clen] = newrow ; + C [clen] = x ; + clen++ ; +#ifndef NDEBUG + if (Diagonal_map && (newrow == Diagonal_map [k])) + { + DEBUG0 (("Diagonal: old: row "ID" col "ID" : " + "new: row "ID" col "ID" : ", + oldrow, oldcol, newrow, k)) ; + EDEBUGk (0, x) ; + } +#endif + } + } + + if (clen != esize) + { + /* :: pattern change (singleton column too short) :: */ + DEBUGm4 (("bad A column (too short)\n")) ; + return (FALSE) ; /* pattern changed */ + } + } + + /* ---------------------------------------------------------------------- */ + /* free the Rpi and Rpx workspace at the tail end of memory */ + /* ---------------------------------------------------------------------- */ + + UMF_mem_free_tail_block (Numeric, rpi) ; + UMF_mem_free_tail_block (Numeric, rpx) ; + + /* ---------------------------------------------------------------------- */ + /* prune zeros and small entries from the singleton rows and columns */ + /* ---------------------------------------------------------------------- */ + + if (n1 > 0) + { + pnew = Lip [0] ; + ASSERT (pnew == 1) ; + for (k = 0 ; k < n1 ; k++) + { + DEBUGm4 (("\nPrune singleton L col "ID"\n", k)) ; + pnew = packsp (pnew, &Lip [k], &Lilen [k], drop, droptol, Memory) ; + Numeric->lnz += Lilen [k] ; + DEBUGm4 (("\nPrune singleton U row "ID"\n", k)) ; + pnew = packsp (pnew, &Uip [k], &Uilen [k], drop, droptol, Memory) ; + Numeric->unz += Uilen [k] ; + } + /* free the unused space at the head of memory */ + Numeric->ihead = pnew ; + } + + /* ---------------------------------------------------------------------- */ + /* initialize row degrees */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + if (Wp [k] != 0) + { + /* :: pattern change (singleton row too short) :: */ + DEBUGm4 (("bad U singleton row (too short)\n")) ; + return (FALSE) ; /* pattern changed */ + } + } + + for (k = n1 ; k < n_row ; k++) + { + DEBUG1 (("Initial row degree k "ID" oldrow "ID" Rdeg "ID"\n", + k, Rperm_init [k], Rdeg [k])) ; + rdeg = Rdeg [k] ; + Row_degree [k] = rdeg ; + if (rdeg > dense_row_threshold && Wp [k] != 0) + { + /* :: pattern change (dense row too short) :: */ + DEBUGm4 (("bad dense row (too short)\n")) ; + return (FALSE) ; /* pattern changed */ + } + } + +#ifndef NDEBUG + if (prefer_diagonal) + { + Entry aij ; + Int *InvCperm, newcol ; + UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, n1, nn, nempty) ; + InvCperm = (Int *) malloc (n_col * sizeof (Int)) ; + ASSERT (InvCperm != (Int *) NULL) ; + for (newcol = 0 ; newcol < n_col ; newcol++) + { + oldcol = Cperm_init [newcol] ; + InvCperm [oldcol] = newcol ; + } + DEBUGm3 (("Diagonal of P2*A:\n")) ; + for (oldcol = 0 ; oldcol < n_col ; oldcol++) + { + newcol = InvCperm [oldcol] ; + for (p = Ap [oldcol] ; p < Ap [oldcol+1] ; p++) + { + oldrow = Ai [p] ; + newrow = Frpos [oldrow] ; + ASSIGN (aij, Ax, Az, p, split) ; + if (newrow == Diagonal_map [newcol]) + { + DEBUG0 (("old row "ID" col "ID" new row "ID" col "ID, + oldrow, oldcol, newrow, newcol)) ; + EDEBUGk (0, aij) ; + DEBUG0 ((" scaled ")) ; + if (do_scale) + { +#ifndef NRECIPROCAL + if (do_recip) + { + SCALE (aij, Rs [oldrow]) ; + } + else +#endif + { + SCALE_DIV (aij, Rs [oldrow]) ; + } + } + EDEBUGk (0, aij) ; + DEBUG0 (("\n")) ; + } + } + } + free (InvCperm) ; + } +#endif + + Col_degree [n_col] = 0 ; + + /* ---------------------------------------------------------------------- */ + /* pack the element name space */ + /* ---------------------------------------------------------------------- */ + + if (empty_elements) + { + Int e2 = 0 ; + DEBUG0 (("\n\n============= Packing element space\n")) ; + for (e = 1 ; e <= Work->nel ; e++) + { + if (E [e]) + { + e2++ ; + E [e2] = E [e] ; + } + } + Work->nel = e2 ; + } + +#ifndef NDEBUG + DEBUG0 (("Number of initial elements: "ID"\n", Work->nel)) ; + for (e = 0 ; e <= Work->nel ; e++) UMF_dump_element (Numeric, Work,e,TRUE) ; +#endif + + for (e = Work->nel + 1 ; e < Work->elen ; e++) + { + E [e] = 0 ; + } + + /* Frpos no longer needed */ + for (row = 0 ; row <= n_row ; row++) + { + Frpos [row] = EMPTY ; + } + + /* clear Wp */ + for (i = 0 ; i <= nn ; i++) + { + Wp [i] = EMPTY ; + } + + DEBUG1 (("Kernel init head usage: "ID"\n", Numeric->ihead)) ; + + /* ---------------------------------------------------------------------- */ + /* build the tuple lists */ + /* ---------------------------------------------------------------------- */ + + /* if the memory usage changes, then the pattern has changed */ + + (void) UMF_tuple_lengths (Numeric, Work, &unused) ; + if (!UMF_build_tuples (Numeric, Work)) + { + /* :: pattern change (out of memory in umf_build_tuples) :: */ + /* We ran out of memory, which can only mean that */ + /* the pattern (Ap and or Ai) has changed (gotten larger). */ + DEBUG0 (("Pattern has gotten larger - build tuples failed\n")) ; + return (FALSE) ; /* pattern changed */ + } + + Numeric->init_usage = Numeric->max_usage ; + + /* ---------------------------------------------------------------------- */ + /* construct the row merge sets */ + /* ---------------------------------------------------------------------- */ + + for (i = 0 ; i <= Symbolic->nfr ; i++) + { + Work->Front_new1strow [i] = Symbolic->Front_1strow [i] ; + } + +#ifndef NDEBUG + UMF_dump_rowmerge (Numeric, Symbolic, Work) ; + DEBUG6 (("Column form of original matrix:\n")) ; + UMF_dump_col_matrix (Ax, +#ifdef COMPLEX + Az, +#endif + Ai, Ap, n_row, n_col, nz) ; + UMF_dump_memory (Numeric) ; + UMF_dump_matrix (Numeric, Work, FALSE) ; + DEBUG0 (("kernel init done...\n")) ; +#endif + + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.h b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_init.h @@ -0,0 +1,18 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_kernel_init +( + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.c b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.c @@ -0,0 +1,466 @@ +/* ========================================================================== */ +/* === UMF_kernel_wrapup ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The matrix is factorized. Finish the LU data structure. */ + +#include "umf_internal.h" + +GLOBAL void UMF_kernel_wrapup +( + NumericType *Numeric, + SymbolicType *Symbolic, + WorkType *Work +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry pivot_value ; + double d ; + Entry *D ; + Int i, k, col, row, llen, ulen, *ip, *Rperm, *Cperm, *Lilen, npiv, lp, + *Uilen, *Lip, *Uip, *Cperm_init, up, pivrow, pivcol, *Lpos, *Upos, *Wr, + *Wc, *Wp, *Frpos, *Fcpos, *Row_degree, *Col_degree, *Rperm_init, + n_row, n_col, n_inner, zero_pivot, nan_pivot, n1 ; + +#ifndef NDEBUG + UMF_dump_matrix (Numeric, Work, FALSE) ; +#endif + + DEBUG0 (("Kernel complete, Starting Kernel wrapup\n")) ; + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + n_inner = MIN (n_row, n_col) ; + Rperm = Numeric->Rperm ; + Cperm = Numeric->Cperm ; + Lilen = Numeric->Lilen ; + Uilen = Numeric->Uilen ; + Upos = Numeric->Upos ; + Lpos = Numeric->Lpos ; + Lip = Numeric->Lip ; + Uip = Numeric->Uip ; + D = Numeric->D ; + + npiv = Work->npiv ; + Numeric->npiv = npiv ; + Numeric->ulen = Work->ulen ; + + ASSERT (n_row == Numeric->n_row) ; + ASSERT (n_col == Symbolic->n_col) ; + DEBUG0 (("Wrap-up: npiv "ID" ulen "ID"\n", npiv, Numeric->ulen)) ; + ASSERT (npiv <= n_inner) ; + + /* this will be nonzero only if matrix is singular or rectangular */ + ASSERT (IMPLIES (npiv == n_col, Work->ulen == 0)) ; + + /* ---------------------------------------------------------------------- */ + /* find the smallest and largest entries in D */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < npiv ; k++) + { + pivot_value = D [k] ; + ABS (d, pivot_value) ; + zero_pivot = SCALAR_IS_ZERO (d) ; + nan_pivot = SCALAR_IS_NAN (d) ; + + if (!zero_pivot) + { + /* the pivot is nonzero, but might be Inf or NaN */ + Numeric->nnzpiv++ ; + } + + if (k == 0) + { + Numeric->min_udiag = d ; + Numeric->max_udiag = d ; + } + else + { + /* min (abs (diag (U))) behaves as follows: If any entry is zero, + then the result is zero (regardless of the presence of NaN's). + Otherwise, if any entry is NaN, then the result is NaN. + Otherwise, the result is the smallest absolute value on the + diagonal of U. + */ + + if (SCALAR_IS_NONZERO (Numeric->min_udiag)) + { + if (zero_pivot || nan_pivot) + { + Numeric->min_udiag = d ; + } + else if (!SCALAR_IS_NAN (Numeric->min_udiag)) + { + /* d and min_udiag are both non-NaN */ + Numeric->min_udiag = MIN (Numeric->min_udiag, d) ; + } + } + + /* + max (abs (diag (U))) behaves as follows: If any entry is NaN + then the result is NaN. Otherise, the result is the largest + absolute value on the diagonal of U. + */ + + if (nan_pivot) + { + Numeric->max_udiag = d ; + } + else if (!SCALAR_IS_NAN (Numeric->max_udiag)) + { + /* d and max_udiag are both non-NaN */ + Numeric->max_udiag = MAX (Numeric->max_udiag, d) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* check if matrix is singular or rectangular */ + /* ---------------------------------------------------------------------- */ + + Col_degree = Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Rperm ; /* for NON_PIVOTAL_ROW macro */ + + if (npiv < n_row) + { + /* finalize the row permutation */ + k = npiv ; + DEBUGm3 (("Singular pivot rows "ID" to "ID"\n", k, n_row-1)) ; + for (row = 0 ; row < n_row ; row++) + { + if (NON_PIVOTAL_ROW (row)) + { + Rperm [row] = ONES_COMPLEMENT (k) ; + DEBUGm3 (("Singular row "ID" is k: "ID" pivot row\n", row, k)) ; + ASSERT (!NON_PIVOTAL_ROW (row)) ; + Lpos [row] = EMPTY ; + Uip [row] = EMPTY ; + Uilen [row] = 0 ; + k++ ; + } + } + ASSERT (k == n_row) ; + } + + if (npiv < n_col) + { + /* finalize the col permutation */ + k = npiv ; + DEBUGm3 (("Singular pivot cols "ID" to "ID"\n", k, n_col-1)) ; + for (col = 0 ; col < n_col ; col++) + { + if (NON_PIVOTAL_COL (col)) + { + Cperm [col] = ONES_COMPLEMENT (k) ; + DEBUGm3 (("Singular col "ID" is k: "ID" pivot row\n", col, k)) ; + ASSERT (!NON_PIVOTAL_COL (col)) ; + Upos [col] = EMPTY ; + Lip [col] = EMPTY ; + Lilen [col] = 0 ; + k++ ; + } + } + ASSERT (k == n_col) ; + } + + if (npiv < n_inner) + { + /* finalize the diagonal of U */ + DEBUGm3 (("Diag of U is zero, "ID" to "ID"\n", npiv, n_inner-1)) ; + for (k = npiv ; k < n_inner ; k++) + { + CLEAR (D [k]) ; + } + } + + /* save the pattern of the last row of U */ + if (Numeric->ulen > 0) + { + DEBUGm3 (("Last row of U is not empty\n")) ; + Numeric->Upattern = Work->Upattern ; + Work->Upattern = (Int *) NULL ; + } + + DEBUG2 (("Nnzpiv: "ID" npiv "ID"\n", Numeric->nnzpiv, npiv)) ; + ASSERT (Numeric->nnzpiv <= npiv) ; + if (Numeric->nnzpiv < n_inner && !SCALAR_IS_NAN (Numeric->min_udiag)) + { + /* the rest of the diagonal is zero, so min_udiag becomes 0, + * unless it is already NaN. */ + Numeric->min_udiag = 0.0 ; + } + + /* ---------------------------------------------------------------------- */ + /* size n_row, n_col workspaces that can be used here: */ + /* ---------------------------------------------------------------------- */ + + Frpos = Work->Frpos ; /* of size n_row+1 */ + Fcpos = Work->Fcpos ; /* of size n_col+1 */ + Wp = Work->Wp ; /* of size MAX(n_row,n_col)+1 */ + /* Work->Upattern ; cannot be used (in Numeric) */ + Wr = Work->Lpattern ; /* of size n_row+1 */ + Wc = Work->Wrp ; /* of size n_col+1 or bigger */ + + /* ---------------------------------------------------------------------- */ + /* construct Rperm from inverse permutations */ + /* ---------------------------------------------------------------------- */ + + /* use Frpos for temporary copy of inverse row permutation [ */ + + for (pivrow = 0 ; pivrow < n_row ; pivrow++) + { + k = Rperm [pivrow] ; + ASSERT (k < 0) ; + k = ONES_COMPLEMENT (k) ; + ASSERT (k >= 0 && k < n_row) ; + Wp [k] = pivrow ; + Frpos [pivrow] = k ; + } + for (k = 0 ; k < n_row ; k++) + { + Rperm [k] = Wp [k] ; + } + + /* ---------------------------------------------------------------------- */ + /* construct Cperm from inverse permutation */ + /* ---------------------------------------------------------------------- */ + + /* use Fcpos for temporary copy of inverse column permutation [ */ + + for (pivcol = 0 ; pivcol < n_col ; pivcol++) + { + k = Cperm [pivcol] ; + ASSERT (k < 0) ; + k = ONES_COMPLEMENT (k) ; + ASSERT (k >= 0 && k < n_col) ; + Wp [k] = pivcol ; + /* save a copy of the inverse column permutation in Fcpos */ + Fcpos [pivcol] = k ; + } + for (k = 0 ; k < n_col ; k++) + { + Cperm [k] = Wp [k] ; + } + +#ifndef NDEBUG + for (k = 0 ; k < n_col ; k++) + { + col = Cperm [k] ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (Fcpos [col] == k) ; /* col is the kth pivot */ + } + for (k = 0 ; k < n_row ; k++) + { + row = Rperm [k] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == k) ; /* row is the kth pivot */ + } +#endif + +#ifndef NDEBUG + UMF_dump_lu (Numeric) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* permute Lpos, Upos, Lilen, Lip, Uilen, and Uip */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < npiv ; k++) + { + pivrow = Rperm [k] ; + Wr [k] = Uilen [pivrow] ; + Wp [k] = Uip [pivrow] ; + } + + for (k = 0 ; k < npiv ; k++) + { + Uilen [k] = Wr [k] ; + Uip [k] = Wp [k] ; + } + + for (k = 0 ; k < npiv ; k++) + { + pivrow = Rperm [k] ; + Wp [k] = Lpos [pivrow] ; + } + + for (k = 0 ; k < npiv ; k++) + { + Lpos [k] = Wp [k] ; + } + + for (k = 0 ; k < npiv ; k++) + { + pivcol = Cperm [k] ; + Wc [k] = Lilen [pivcol] ; + Wp [k] = Lip [pivcol] ; + } + + for (k = 0 ; k < npiv ; k++) + { + Lilen [k] = Wc [k] ; + Lip [k] = Wp [k] ; + } + + for (k = 0 ; k < npiv ; k++) + { + pivcol = Cperm [k] ; + Wp [k] = Upos [pivcol] ; + } + + for (k = 0 ; k < npiv ; k++) + { + Upos [k] = Wp [k] ; + } + + /* ---------------------------------------------------------------------- */ + /* terminate the last Uchain and last Lchain */ + /* ---------------------------------------------------------------------- */ + + Upos [npiv] = EMPTY ; + Lpos [npiv] = EMPTY ; + Uip [npiv] = EMPTY ; + Lip [npiv] = EMPTY ; + Uilen [npiv] = 0 ; + Lilen [npiv] = 0 ; + + /* ---------------------------------------------------------------------- */ + /* convert U to the new pivot order */ + /* ---------------------------------------------------------------------- */ + + n1 = Symbolic->n1 ; + + for (k = 0 ; k < n1 ; k++) + { + /* this is a singleton row of U */ + ulen = Uilen [k] ; + DEBUG4 (("K "ID" New U. ulen "ID" Singleton 1\n", k, ulen)) ; + if (ulen > 0) + { + up = Uip [k] ; + ip = (Int *) (Numeric->Memory + up) ; + for (i = 0 ; i < ulen ; i++) + { + col = *ip ; + DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col])); + ASSERT (col >= 0 && col < n_col) ; + *ip++ = Fcpos [col] ; + } + } + } + + for (k = n1 ; k < npiv ; k++) + { + up = Uip [k] ; + if (up < 0) + { + /* this is the start of a new Uchain (with a pattern) */ + ulen = Uilen [k] ; + DEBUG4 (("K "ID" New U. ulen "ID" End_Uchain 1\n", k, ulen)) ; + if (ulen > 0) + { + up = -up ; + ip = (Int *) (Numeric->Memory + up) ; + for (i = 0 ; i < ulen ; i++) + { + col = *ip ; + DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col])); + ASSERT (col >= 0 && col < n_col) ; + *ip++ = Fcpos [col] ; + } + } + } + } + + ulen = Numeric->ulen ; + if (ulen > 0) + { + /* convert last pivot row of U to the new pivot order */ + DEBUG4 (("K "ID" (last)\n", k)) ; + for (i = 0 ; i < ulen ; i++) + { + col = Numeric->Upattern [i] ; + DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col])) ; + Numeric->Upattern [i] = Fcpos [col] ; + } + } + + /* Fcpos no longer needed ] */ + + /* ---------------------------------------------------------------------- */ + /* convert L to the new pivot order */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + llen = Lilen [k] ; + DEBUG4 (("K "ID" New L. llen "ID" Singleton col\n", k, llen)) ; + if (llen > 0) + { + lp = Lip [k] ; + ip = (Int *) (Numeric->Memory + lp) ; + for (i = 0 ; i < llen ; i++) + { + row = *ip ; + DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ; + ASSERT (row >= 0 && row < n_row) ; + *ip++ = Frpos [row] ; + } + } + } + + for (k = n1 ; k < npiv ; k++) + { + llen = Lilen [k] ; + DEBUG4 (("K "ID" New L. llen "ID" \n", k, llen)) ; + if (llen > 0) + { + lp = Lip [k] ; + if (lp < 0) + { + /* this starts a new Lchain */ + lp = -lp ; + } + ip = (Int *) (Numeric->Memory + lp) ; + for (i = 0 ; i < llen ; i++) + { + row = *ip ; + DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ; + ASSERT (row >= 0 && row < n_row) ; + *ip++ = Frpos [row] ; + } + } + } + + /* Frpos no longer needed ] */ + + /* ---------------------------------------------------------------------- */ + /* combine symbolic and numeric permutations */ + /* ---------------------------------------------------------------------- */ + + Cperm_init = Symbolic->Cperm_init ; + Rperm_init = Symbolic->Rperm_init ; + + for (k = 0 ; k < n_row ; k++) + { + Rperm [k] = Rperm_init [Rperm [k]] ; + } + + for (k = 0 ; k < n_col ; k++) + { + Cperm [k] = Cperm_init [Cperm [k]] ; + } + + /* Work object will be freed immediately upon return (to UMF_kernel */ + /* and then to UMFPACK_numeric). */ +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.h b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_kernel_wrapup.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_kernel_wrapup +( + NumericType *Numeric, + SymbolicType *Symbolic, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.c b/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.c @@ -0,0 +1,1947 @@ +/* ========================================================================== */ +/* === UMF_local_search ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Perform pivot search to find pivot row and pivot column. + The pivot column is selected from the candidate set. The candidate set + corresponds to a supercolumn from colamd or UMF_analyze. The pivot column + is then removed from that set. Constructs the pivot column pattern and + values. Called by umf_kernel. Returns UMFPACK_OK if successful, or + UMFPACK_WARNING_singular_matrix or UMFPACK_ERROR_different_pattern if not. +*/ + +#include "umf_internal.h" +#include "umf_row_search.h" +#include "umf_mem_free_tail_block.h" + +/* relaxed amalgamation control parameters are fixed at compile time */ +#define RELAX1 0.25 +#define SYM_RELAX1 0.0 +#define RELAX2 0.1 +#define RELAX3 0.125 + +/* ========================================================================== */ +/* === remove_candidate ===================================================== */ +/* ========================================================================== */ + +/* Remove a column from the set of candidate pivot columns. */ + +PRIVATE void remove_candidate (Int jj, WorkType *Work, SymbolicType *Symbolic) +{ + +#ifndef NDEBUG + Int j ; + DEBUGm2 (("pivot column Candidates before remove: nCand "ID" ncand "ID + " lo "ID" hi "ID" jj "ID"\n", Work->nCandidates, Work->ncand, + Work->lo, Work->hi, jj)) ; + for (j = 0 ; j < Work->nCandidates ; j++) + { + Int col = Work->Candidates [j] ; + DEBUGm2 ((ID" ", col)); + ASSERT (col >= 0 && col < Work->n_col) ; + /* ASSERT (NON_PIVOTAL_COL (col)) ; */ + ASSERT (col >= Work->lo && col <= Work->hi) ; + } + DEBUGm2 (("\n")) ; +#endif + + if (Symbolic->fixQ) + { + DEBUGm2 (("FixQ\n")) ; + /* do not modify the column ordering */ + ASSERT (Work->nCandidates == 1) ; + ASSERT (jj == 0) ; + if (Work->ncand > 1) + { + Work->Candidates [0] = Work->nextcand++ ; + } + else + { + Work->nCandidates = 0 ; + } + } + else + { + /* place the next candidate in the set */ + if (Work->ncand > MAX_CANDIDATES) + { + Work->Candidates [jj] = Work->nextcand++ ; + } + else + { + ASSERT (Work->nCandidates == Work->ncand) ; + Work->Candidates [jj] = Work->Candidates [Work->ncand - 1] ; + Work->Candidates [Work->ncand - 1] = EMPTY ; + Work->nCandidates-- ; + } + } + Work->ncand-- ; + +#ifndef NDEBUG + DEBUGm2 (("pivot column Candidates after remove: nCand "ID" ncand "ID + " lo "ID" hi "ID" jj "ID"\n", Work->nCandidates, Work->ncand, Work->lo, + Work->hi, jj)) ; + for (j = 0 ; j < Work->nCandidates ; j++) + { + Int col = Work->Candidates [j] ; + DEBUGm2 ((ID" ", col)); + ASSERT (col >= 0 && col < Work->n_col) ; + /* ASSERT (NON_PIVOTAL_COL (col)) ; */ + ASSERT (col >= Work->lo && col <= Work->hi) ; + } + DEBUGm2 (("\n")) ; + ASSERT (Work->ncand >= 0) ; + ASSERT (Work->nCandidates <= Work->ncand) ; +#endif +} + +/* ========================================================================== */ +/* === UMF_local_search ===================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMF_local_search +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double relax1 ; + Entry *Flblock, *Fublock, *Fs, *Fcblock, *C, *Wx, *Wy, *Fu, *Flublock, + *Flu ; + Int pos, nrows, *Cols, *Rows, e, f, status, max_cdeg, fnzeros, nb, j, col, + i, row, cdeg_in, rdeg [2][2], fnpiv, nothing [2], new_LUsize, + pivrow [2][2], pivcol [2], *Wp, *Fcpos, *Frpos, new_fnzeros, cdeg_out, + *Wm, *Wio, *Woi, *Woo, *Frows, *Fcols, fnrows, fncols, *E, deg, nr_in, + nc, thiscost, bestcost, nr_out, do_update, extra_cols, extra_rows, + extra_zeros, relaxed_front, do_extend, fnr_curr, fnc_curr, tpi, + *Col_tuples, *Col_degree, *Col_tlen, jj, jcand [2], freebie [2], + did_rowmerge, fnrows_new [2][2], fncols_new [2][2], search_pivcol_out, + *Diagonal_map, *Diagonal_imap, row2, col2 ; + Unit *Memory, *p ; + Tuple *tp, *tpend, *tp1, *tp2 ; + Element *ep ; + +#ifndef NDEBUG + Int debug_ok, n_row, n_col, *Row_degree ; + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro only */ +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + Memory = Numeric->Memory ; + E = Work->E ; + Col_degree = Numeric->Cperm ; + + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + + Wx = Work->Wx ; + Wy = Work->Wy ; + Wp = Work->Wp ; + Wm = Work->Wm ; + Woi = Work->Woi ; + Wio = Work->Wio ; + Woo = Work->Woo ; + Fcpos = Work->Fcpos ; + Frpos = Work->Frpos ; + Frows = Work->Frows ; + Fcols = Work->Fcols ; + fnrows = Work->fnrows ; + fncols = Work->fncols ; + nb = Work->nb ; + fnr_curr = Work->fnr_curr ; + fnc_curr = Work->fnc_curr ; + fnpiv = Work->fnpiv ; + nothing [0] = EMPTY ; + nothing [1] = EMPTY ; + relax1 = (Symbolic->prefer_diagonal) ? SYM_RELAX1 : RELAX1 ; + fnzeros = Work->fnzeros ; + new_fnzeros = fnzeros ; + jj = EMPTY ; + + Fcblock = Work->Fcblock ; /* current contribution block */ + Flblock = Work->Flblock ; /* current L block */ + Fublock = Work->Fublock ; /* current U block */ + Flublock = Work->Flublock ; /* current LU block */ + + /* The pivot column degree cannot exceed max_cdeg */ + max_cdeg = Work->fnrows_max ; + ASSERT (Work->fnrows_max <= Symbolic->maxnrows) ; + ASSERT (Work->fncols_max <= Symbolic->maxncols) ; + + if (fnrows == 0 && fncols == 0) + { + /* frontal matrix is empty */ + Work->firstsuper = Work->ksuper ; + } + +#ifndef NDEBUG + n_row = Work->n_row ; + n_col = Work->n_col ; + DEBUG2 (("\n========LOCAL SEARCH: current frontal matrix: ========= \n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; + if (UMF_debug > 0 || MAX (n_row, n_col) < 1000) + { + for (i = 0 ; i < MAX (n_row, n_col) ; i++) + { + ASSERT (Wp [i] < 0) ; + } + } + + DEBUGm2 ((ID" pivot column Candidates: lo "ID" hi "ID"\n", + Work->nCandidates, Work->lo, Work->hi)) ; + for (j = 0 ; j < Work->nCandidates ; j++) + { + col = Work->Candidates [j] ; + DEBUGm2 ((ID" ", col)); + ASSERT (col >= 0 && col < n_col) ; + ASSERT (NON_PIVOTAL_COL (col)) ; + ASSERT (col >= Work->lo && col <= Work->hi) ; + } + + DEBUGm2 (("\n")) ; + /* there are no 0-by-c or r-by-0 fronts, where c and r are > 0 */ + /* a front is either 0-by-0, or r-by-c */ + DEBUG2 (("\n\n::: "ID" : Npiv: "ID" + fnpiv "ID" = "ID". " + "size "ID"-by-"ID"\n", Work->frontid, + Work->npiv, Work->fnpiv, Work->npiv + Work->fnpiv, fnrows, fncols)) ; + ASSERT ((fnrows == 0 && fncols == 0) ||(fnrows != 0 && fncols != 0)) ; +#endif + + /* ====================================================================== */ + /* === PIVOT SEARCH ===================================================== */ + /* ====================================================================== */ + + /* initialize */ + + pivcol [IN] = EMPTY ; + pivcol [OUT] = EMPTY ; + + cdeg_in = Int_MAX ; + cdeg_out = Int_MAX ; + + pivrow [IN][IN] = EMPTY ; + pivrow [IN][OUT] = EMPTY ; + pivrow [OUT][IN] = EMPTY ; + pivrow [OUT][OUT] = EMPTY ; + + rdeg [IN][IN] = Int_MAX ; + rdeg [IN][OUT] = Int_MAX ; + rdeg [OUT][IN] = Int_MAX ; + rdeg [OUT][OUT] = Int_MAX ; + + freebie [IN] = FALSE ; + freebie [OUT] = FALSE ; + + Work->pivot_case = EMPTY ; + bestcost = EMPTY ; + + nr_out = EMPTY ; + nr_in = EMPTY ; + + jcand [IN] = EMPTY ; + jcand [OUT] = EMPTY ; + + fnrows_new [IN][IN] = EMPTY ; + fnrows_new [IN][OUT] = EMPTY ; + fnrows_new [OUT][IN] = EMPTY ; + fnrows_new [OUT][OUT] = EMPTY ; + + fncols_new [IN][IN] = EMPTY ; + fncols_new [IN][OUT] = EMPTY ; + fncols_new [OUT][IN] = EMPTY ; + fncols_new [OUT][OUT] = EMPTY ; + +#ifndef NDEBUG + /* check Frpos */ + DEBUG4 (("Check Frpos : fnrows "ID" col "ID" maxcdeg "ID"\n", + fnrows, pivcol [IN], max_cdeg)) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Frows [i] ; + DEBUG4 ((" row: "ID"\n", row)) ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == i) ; + } + DEBUG4 (("All:\n")) ; + if (UMF_debug > 0 || n_row < 1000) + { + Int cnt = fnrows ; + for (row = 0 ; row < n_row ; row++) + { + if (Frpos [row] == EMPTY) + { + cnt++ ; + } + else + { + DEBUG4 ((" row: "ID" pos "ID"\n", row, Frpos [row])) ; + } + } + ASSERT (cnt == n_row) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* find shortest column in the front, and shortest column not in the */ + /* front, from the candidate pivot column set */ + /* ---------------------------------------------------------------------- */ + + /* If there are too many candidates, then only look at the first */ + /* MAX_CANDIDATES of them. Otherwise, if there are O(n) candidates, */ + /* this code could take O(n^2) time. */ + + /* ------------------------------------------------------------------ */ + /* look in the candidate set for the best column */ + /* ------------------------------------------------------------------ */ + + DEBUG2 (("Max candidates %d, Work->ncand "ID" jmax "ID"\n", + MAX_CANDIDATES, Work->ncand, Work->nCandidates)) ; + col = Work->Candidates [0] ; + ASSERT (Work->nCandidates > 0) ; + DEBUG3 (("Pivot column candidate: "ID" j = "ID"\n", col, j)) ; + ASSERT (col >= 0 && col < n_col) ; + + /* there is no Col_degree if fixQ is true */ + deg = Symbolic->fixQ ? EMPTY : Col_degree [col] ; + +#ifndef NDEBUG + DEBUG3 (("Pivot column candidate: "ID" cost: "ID" Fcpos[col] "ID"\n", + col, deg, Fcpos [col])) ; + UMF_dump_rowcol (1, Numeric, Work, col, !Symbolic->fixQ) ; + if (Symbolic->fixQ) + { + DEBUG1 (("FIXQ: Candidates "ID" pivcol "ID" npiv "ID" fnpiv "ID + " ndiscard "ID "\n", Work->nCandidates, col, Work->npiv, + Work->fnpiv, Work->ndiscard)) ; + ASSERT (Work->nCandidates == 1) ; + ASSERT (col == Work->npiv + Work->fnpiv + Work->ndiscard) ; + } +#endif + + if (Fcpos [col] >= 0) + { + /* best column in front, so far */ + pivcol [IN] = col ; + cdeg_in = deg ; /* ignored, if fixQ is true */ + jcand [IN] = 0 ; + } + else + { + /* best column not in front, so far */ + pivcol [OUT] = col ; + cdeg_out = deg ; /* ignored, if fixQ is true */ + jcand [OUT] = 0 ; + } + + /* look at the rest of the candidates */ + for (j = 1 ; j < Work->nCandidates ; j++) + { + col = Work->Candidates [j] ; + + DEBUG3 (("Pivot col candidate: "ID" j = "ID"\n", col, j)) ; + ASSERT (col >= 0 && col < n_col) ; + ASSERT (!Symbolic->fixQ) ; + deg = Col_degree [col] ; +#ifndef NDEBUG + DEBUG3 (("Pivot col candidate: "ID" cost: "ID" Fcpos[col] "ID"\n", + col, deg, Fcpos [col])) ; + UMF_dump_rowcol (1, Numeric, Work, col, !Symbolic->fixQ) ; +#endif + if (Fcpos [col] >= 0) + { +#ifndef NDEBUG + Int fs ; + fs = Fcpos [col] / fnr_curr ; + ASSERT (fs >= 0 && fs < fncols) ; +#endif + if (deg < cdeg_in || (deg == cdeg_in && col < pivcol [IN])) + { + /* best column in front, so far */ + pivcol [IN] = col ; + cdeg_in = deg ; + jcand [IN] = j ; + } + } + else + { + if (deg < cdeg_out || (deg == cdeg_out && col < pivcol [OUT])) + { + /* best column not in front, so far */ + pivcol [OUT] = col ; + cdeg_out = deg ; + jcand [OUT] = j ; + } + } + } + + DEBUG2 (("Pivcol in "ID" out "ID"\n", pivcol [IN], pivcol [OUT])) ; + ASSERT ((pivcol [IN] >= 0 && pivcol [IN] < n_col) + || (pivcol [OUT] >= 0 && pivcol [OUT] < n_col)) ; + + cdeg_in = EMPTY ; + cdeg_out = EMPTY ; + + /* ---------------------------------------------------------------------- */ + /* construct candidate column in front, and search for pivot rows */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + /* check Frpos */ + DEBUG4 (("Prior to col update: fnrows "ID" col "ID" maxcdeg "ID"\n", + fnrows, pivcol [IN], max_cdeg)) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Frows [i] ; + DEBUG4 ((" row: "ID"\n", row)) ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == i) ; + } + DEBUG4 (("All:\n")) ; + if (UMF_debug > 0 || n_row < 1000) + { + Int cnt = fnrows ; + for (row = 0 ; row < n_row ; row++) + { + if (Frpos [row] == EMPTY) + { + cnt++ ; + } + else + { + DEBUG4 ((" row: "ID" pos "ID"\n", row, Frpos [row])) ; + } + } + ASSERT (cnt == n_row) ; + } +#endif + + if (pivcol [IN] != EMPTY) + { + +#ifndef NDEBUG + DEBUG2 (("col[IN] column "ID" in front at position = "ID"\n", + pivcol [IN], Fcpos [pivcol [IN]])) ; + UMF_dump_rowcol (1, Numeric, Work, pivcol [IN], !Symbolic->fixQ) ; +#endif + + /* the only way we can have a pivcol[IN] is if the front is not empty */ + ASSERT (fnrows > 0 && fncols > 0) ; + + DEBUG4 (("Update pivot column:\n")) ; + Fs = Fcblock + Fcpos [pivcol [IN]] ; + Fu = Fublock + (Fcpos [pivcol [IN]] / fnr_curr) ; + Flu = Flublock + fnpiv * nb ; + + /* ------------------------------------------------------------------ */ + /* copy the pivot column from the U block into the LU block */ + /* ------------------------------------------------------------------ */ + + /* This copy is permanent if the pivcol [IN] is chosen. */ + for (i = 0 ; i < fnpiv ; i++) + { + Flu [i] = Fu [i*fnc_curr] ; + } + + /* ------------------------------------------------------------------ */ + /* update the pivot column in the LU block using a triangular solve */ + /* ------------------------------------------------------------------ */ + + /* This work will be discarded if the pivcol [OUT] is chosen instead. + * It is permanent if the pivcol [IN] is chosen. */ + + if (fnpiv > 1) + { + /* solve Lx=b, where b = U (:,k), stored in the LU block */ + +#ifdef USE_NO_BLAS + + /* no BLAS available - use plain C code instead */ + Entry *Flub = Flublock ; + for (j = 0 ; j < fnpiv ; j++) + { + Entry Fuj = Flu [j] ; +#pragma ivdep + for (i = j+1 ; i < fnpiv ; i++) + { + /* Flu [i] -= Flublock [i + j*nb] * Flu [j] ; */ + MULT_SUB (Flu [i], Flub [i], Fuj) ; + } + Flub += nb ; + } + +#else + BLAS_TRSV (fnpiv, Flublock, Flu, nb) ; +#endif + + } + + /* ------------------------------------------------------------------ */ + /* copy the pivot column from the C block into Wy */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < fnrows ; i++) + { + Wy [i] = Fs [i] ; + } + + /* ------------------------------------------------------------------ */ + /* update the pivot column of L using a matrix-vector multiply */ + /* ------------------------------------------------------------------ */ + + /* this work will be discarded if the pivcol [OUT] is chosen instead */ + +#ifdef USE_NO_BLAS + /* no BLAS available - use plain C code instead */ + for (j = 0 ; j < fnpiv ; j++) + { + Entry Fuj, *Flub = Flblock + j * fnr_curr ; + Fuj = Flu [j] ; + if (IS_NONZERO (Fuj)) + { +#pragma ivdep + for (i = 0 ; i < fnrows ; i++) + { + /* Wy [i] -= Flblock [i+j*fnr_curr] * Fuj ; */ + MULT_SUB (Wy [i], Flub [i], Fuj) ; + } + } + /* Flblock += fnr_curr ; */ + } +#else + /* Using 1-based notation: + * Wy (1:fnrows) -= Flblock (1:fnrows,1:fnpiv) * Flu (1:fnpiv) */ + BLAS_GEMV (fnrows, fnpiv, Flblock, Flu, Wy, fnr_curr) ; +#endif + + /* ------------------------------------------------------------------ */ + +#ifndef NDEBUG + DEBUG2 (("Wy after update: fnrows="ID"\n", fnrows)) ; + DEBUG4 ((" fnpiv="ID" \n", fnpiv)) ; + for (i = 0 ; i < fnrows ; i++) + { + DEBUG4 ((ID" "ID" "ID, i, Frows [i], Frpos [Frows [i]])) ; + EDEBUG4 (Wy [i]) ; + DEBUG4 (("\n")) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* construct the candidate column */ + /* ------------------------------------------------------------------ */ + + cdeg_in = fnrows ; + +#ifndef NDEBUG + /* check Frpos */ + DEBUG4 (("After col update: fnrows "ID" col "ID" maxcdeg "ID"\n", + fnrows, pivcol [IN], max_cdeg)) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Frows [i] ; + DEBUG4 ((" row: "ID"\n", row)) ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == i) ; + } + DEBUG4 (("All:\n")) ; + if (UMF_debug > 0 || n_row < 1000) + { + Int cnt = fnrows ; + for (row = 0 ; row < n_row ; row++) + { + if (Frpos [row] == EMPTY) + { + cnt++ ; + } + else + { + DEBUG4 ((" row: "ID" pos "ID"\n", row, Frpos [row])) ; + } + } + ASSERT (cnt == n_row) ; + } +#endif + +#ifndef NDEBUG + /* check Frpos */ + DEBUG4 (("COL ASSEMBLE: cdeg "ID"\nREDUCE COL in "ID" max_cdeg "ID"\n", + cdeg_in, pivcol [IN], max_cdeg)) ; + for (i = 0 ; i < cdeg_in ; i++) + { + row = Frows [i] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == i) ; + } + if (UMF_debug > 0 || n_row < 1000) + { + Int cnt = cdeg_in ; + for (row = 0 ; row < n_row ; row++) + { + if (Frpos [row] == EMPTY) cnt++ ; + } + ASSERT (cnt == n_row) ; + } +#endif + + /* assemble column into Wy */ + + ASSERT (pivcol [IN] >= 0 && pivcol [IN] < n_col) ; + ASSERT (NON_PIVOTAL_COL (pivcol [IN])) ; + + tpi = Col_tuples [pivcol [IN]] ; + if (tpi) + { + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Col_tlen [pivcol [IN]] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + if (Cols [f] == EMPTY) continue ; /* column already assembled */ + ASSERT (pivcol [IN] == Cols [f]) ; + + Rows = Cols + ep->ncols ; + nrows = ep->nrows ; + p += UNITS (Int, ep->ncols + nrows) ; + C = ((Entry *) p) + f * nrows ; + + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) /* skip this if already gone from element */ + { + ASSERT (row < n_row) ; + pos = Frpos [row] ; + if (pos < 0) + { + /* new entry in the pattern - save Frpos */ + ASSERT (cdeg_in < n_row) ; + if (cdeg_in >= max_cdeg) + { + /* :: pattern change (cdeg in failure) :: */ + DEBUGm4 (("cdeg_in failure\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + Frpos [row] = cdeg_in ; + Frows [cdeg_in] = row ; + Wy [cdeg_in++] = C [i] ; + } + else + { + /* entry already in pattern - sum values in Wy */ + /* Wy [pos] += C [i] ; */ + ASSERT (pos < max_cdeg) ; + ASSEMBLE (Wy [pos], C [i]) ; + } + } + } + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Col_tlen [pivcol [IN]] = tp2 - tp1 ; + } + + /* ------------------------------------------------------------------ */ + +#ifndef NDEBUG + /* check Frpos again */ + DEBUG4 (("COL DONE: cdeg "ID"\nREDUCE COL in "ID" max_cdeg "ID"\n", + cdeg_in, pivcol [IN], max_cdeg)) ; + for (i = 0 ; i < cdeg_in ; i++) + { + row = Frows [i] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (Frpos [row] == i) ; + } + if (UMF_debug > 0 || n_row < 1000) + { + Int cnt = cdeg_in ; + for (row = 0 ; row < n_row ; row++) + { + if (Frpos [row] == EMPTY) cnt++ ; + } + ASSERT (cnt == n_row) ; + } +#endif + +#ifndef NDEBUG + DEBUG4 (("Reduced column: cdeg in "ID" fnrows_max "ID"\n", + cdeg_in, Work->fnrows_max)) ; + for (i = 0 ; i < cdeg_in ; i++) + { + DEBUG4 ((" "ID" "ID" "ID, i, Frows [i], Frpos [Frows [i]])) ; + EDEBUG4 (Wy [i]) ; + DEBUG4 (("\n")) ; + ASSERT (i == Frpos [Frows [i]]) ; + } + ASSERT (cdeg_in <= Work->fnrows_max) ; +#endif + + /* ------------------------------------------------------------------ */ + /* cdeg_in is now the exact degree of this column */ + /* ------------------------------------------------------------------ */ + + nr_in = cdeg_in - fnrows ; + + /* since there are no 0-by-x fronts, if there is a pivcol [IN] the */ + /* front must have at least one row. */ + ASSERT (cdeg_in > 0) ; + + /* new degree of pivcol [IN], excluding current front is nr_in */ + /* column expands by nr_in rows */ + + /* ------------------------------------------------------------------ */ + /* search for two candidate pivot rows */ + /* ------------------------------------------------------------------ */ + + /* for the IN_IN pivot row (if any), */ + /* extend the pattern in place, using Fcols */ + status = UMF_row_search (Numeric, Work, Symbolic, + fnrows, cdeg_in, Frows, Frpos, /* pattern of column to search */ + pivrow [IN], rdeg [IN], Fcols, Wio, nothing, Wy, + pivcol [IN], freebie) ; + ASSERT (!freebie [IN] && !freebie [OUT]) ; + + /* ------------------------------------------------------------------ */ + /* fatal error if matrix pattern has changed since symbolic analysis */ + /* ------------------------------------------------------------------ */ + + if (status == UMFPACK_ERROR_different_pattern) + { + /* :: pattern change (row search IN failure) :: */ + DEBUGm4 (("row search IN failure\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + + /* ------------------------------------------------------------------ */ + /* we now must have a structural pivot */ + /* ------------------------------------------------------------------ */ + + /* Since the pivcol[IN] exists, there must be at least one row in the */ + /* current frontal matrix, and so we must have found a structural */ + /* pivot. The numerical value might be zero, of course. */ + + ASSERT (status != UMFPACK_WARNING_singular_matrix) ; + + /* ------------------------------------------------------------------ */ + /* evaluate IN_IN option */ + /* ------------------------------------------------------------------ */ + + if (pivrow [IN][IN] != EMPTY) + { + /* The current front would become an (implicit) LUson. + * Both candidate pivot row and column are in the current front. + * Cost is how much the current front would expand */ + + /* pivrow[IN][IN] candidates are not found via row merge search */ + + ASSERT (fnrows >= 0 && fncols >= 0) ; + + ASSERT (cdeg_in > 0) ; + nc = rdeg [IN][IN] - fncols ; + + thiscost = + /* each column in front (except pivot column) grows by nr_in: */ + (nr_in * (fncols - 1)) + + /* new columns not in old front: */ + (nc * (cdeg_in - 1)) ; + + /* no extra cost to relaxed amalgamation */ + + ASSERT (fnrows + nr_in == cdeg_in) ; + ASSERT (fncols + nc == rdeg [IN][IN]) ; + + /* size of relaxed front (after pivot row column removed): */ + fnrows_new [IN][IN] = (fnrows-1) + nr_in ; + fncols_new [IN][IN] = (fncols-1) + nc ; + /* relaxed_front = fnrows_new [IN][IN] * fncols_new [IN][IN] ; */ + + do_extend = TRUE ; + + DEBUG2 (("Evaluating option IN-IN:\n")) ; + DEBUG2 (("Work->fnzeros "ID" fnpiv "ID" nr_in "ID" nc "ID"\n", + Work->fnzeros, fnpiv, nr_in, nc)) ; + DEBUG2 (("fncols "ID" fnrows "ID"\n", fncols, fnrows)) ; + + /* determine if BLAS-3 update should be applied before extending. */ + /* update if too many zero entries accumulate in the LU block */ + fnzeros = Work->fnzeros + fnpiv * (nr_in + nc) ; + + DEBUG2 (("fnzeros "ID"\n", fnzeros)) ; + + new_LUsize = (fnpiv+1) * (fnrows + nr_in + fncols + nc) ; + + DEBUG2 (("new_LUsize "ID"\n", new_LUsize)) ; + + /* There are fnpiv pivots currently in the front. This one + * will be the (fnpiv+1)st pivot, if it is extended. */ + + /* RELAX2 parameter uses a double relop, but ignore NaN case: */ + do_update = fnpiv > 0 && + (((double) fnzeros) / ((double) new_LUsize)) > RELAX2 ; + + DEBUG2 (("do_update "ID"\n", do_update)) + + DEBUG2 (("option IN IN : nr "ID" nc "ID" cost "ID"(0) relax "ID + "\n", nr_in, nc, thiscost, do_extend)) ; + + /* this is the best option seen so far */ + Work->pivot_case = IN_IN ; + bestcost = thiscost ; + + /* do the amalgamation and extend the front */ + Work->do_extend = do_extend ; + Work->do_update = do_update ; + new_fnzeros = fnzeros ; + + } + + /* ------------------------------------------------------------------ */ + /* evaluate IN_OUT option */ + /* ------------------------------------------------------------------ */ + + if (pivrow [IN][OUT] != EMPTY) + { + /* The current front would become a Uson of the new front. + * Candidate pivot column is in the current front, but the + * candidate pivot row is not. */ + + ASSERT (fnrows >= 0 && fncols > 0) ; + ASSERT (cdeg_in > 0) ; + + /* must be at least one row outside the front */ + /* (the pivrow [IN][OUT] itself) */ + ASSERT (nr_in >= 1) ; + + /* count columns not in current front */ + nc = 0 ; +#ifndef NDEBUG + debug_ok = FALSE ; +#endif + for (i = 0 ; i < rdeg [IN][OUT] ; i++) + { + col = Wio [i] ; + DEBUG4 (("counting col "ID" Fcpos[] = "ID"\n", col, + Fcpos [col])) ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + if (Fcpos [col] < 0) nc++ ; +#ifndef NDEBUG + /* we must see the pivot column somewhere */ + if (col == pivcol [IN]) + { + ASSERT (Fcpos [col] >= 0) ; + debug_ok = TRUE ; + } +#endif + } + ASSERT (debug_ok) ; + + thiscost = + /* each row in front grows by nc: */ + (nc * fnrows) + + /* new rows not affected by front: */ + ((nr_in-1) * (rdeg [IN][OUT]-1)) ; + + /* check the cost of relaxed IN_OUT amalgamation */ + + extra_cols = ((fncols-1) + nc ) - (rdeg [IN][OUT] - 1) ; + ASSERT (extra_cols >= 0) ; + ASSERT (fncols + nc == extra_cols + rdeg [IN][OUT]) ; + extra_zeros = (nr_in-1) * extra_cols ; /* symbolic fill-in */ + + ASSERT (fnrows + nr_in == cdeg_in) ; + ASSERT (fncols + nc == rdeg [IN][OUT] + extra_cols) ; + + /* size of relaxed front (after pivot column removed): */ + fnrows_new [IN][OUT] = fnrows + (nr_in-1) ; + fncols_new [IN][OUT] = (fncols-1) + nc ; + relaxed_front = fnrows_new [IN][OUT] * fncols_new [IN][OUT] ; + + /* do relaxed amalgamation if the extra zeros are no more */ + /* than a fraction (default 0.25) of the relaxed front */ + /* if relax = 0: no extra zeros allowed */ + /* if relax = +inf: always amalgamate */ + + /* relax parameter uses a double relop, but ignore NaN case: */ + if (extra_zeros == 0) + { + do_extend = TRUE ; + } + else + { + do_extend = ((double) extra_zeros) < + (relax1 * (double) relaxed_front) ; + } + + if (do_extend) + { + /* count the cost of relaxed amalgamation */ + thiscost += extra_zeros ; + + DEBUG2 (("Evaluating option IN-OUT:\n")) ; + DEBUG2 (("Work->fnzeros "ID" fnpiv "ID" nr_in "ID" nc "ID"\n", + Work->fnzeros, fnpiv, nr_in, nc)) ; + DEBUG2 (("fncols "ID" fnrows "ID"\n", fncols, fnrows)) ; + + /* determine if BLAS-3 update to be applied before extending. */ + /* update if too many zero entries accumulate in the LU block */ + fnzeros = Work->fnzeros + fnpiv * (nr_in + nc) ; + + DEBUG2 (("fnzeros "ID"\n", fnzeros)) ; + + new_LUsize = (fnpiv+1) * (fnrows + nr_in + fncols + nc) ; + + DEBUG2 (("new_LUsize "ID"\n", new_LUsize)) ; + + /* RELAX3 parameter uses a double relop, ignore NaN case: */ + do_update = fnpiv > 0 && + (((double) fnzeros) / ((double) new_LUsize)) > RELAX3 ; + DEBUG2 (("do_update "ID"\n", do_update)) + + } + else + { + /* the current front would not be extended */ + do_update = fnpiv > 0 ; + fnzeros = 0 ; + DEBUG2 (("IN-OUT do_update forced true: "ID"\n", do_update)) ; + + /* The new front would be just big enough to hold the new + * pivot row and column. */ + fnrows_new [IN][OUT] = cdeg_in - 1 ; + fncols_new [IN][OUT] = rdeg [IN][OUT] - 1 ; + + } + + DEBUG2 (("option IN OUT: nr "ID" nc "ID" cost "ID"("ID") relax "ID + "\n", nr_in, nc, thiscost, extra_zeros, do_extend)) ; + + if (bestcost == EMPTY || thiscost < bestcost) + { + /* this is the best option seen so far */ + Work->pivot_case = IN_OUT ; + bestcost = thiscost ; + Work->do_extend = do_extend ; + Work->do_update = do_update ; + new_fnzeros = fnzeros ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* construct candidate column not in front, and search for pivot rows */ + /* ---------------------------------------------------------------------- */ + + search_pivcol_out = (bestcost != 0 && pivcol [OUT] != EMPTY) ; + if (Symbolic->prefer_diagonal) + { + search_pivcol_out = search_pivcol_out && (pivrow [IN][IN] == EMPTY) ; + } + + if (search_pivcol_out) + { + +#ifndef NDEBUG + DEBUG2 (("out_col column "ID" NOT in front at position = "ID"\n", + pivcol [OUT], Fcpos [pivcol [OUT]])) ; + UMF_dump_rowcol (1, Numeric, Work, pivcol [OUT], !Symbolic->fixQ) ; + DEBUG2 (("fncols "ID" fncols_max "ID"\n", fncols, Work->fncols_max)) ; + ASSERT (fncols < Work->fncols_max) ; +#endif + + /* Use Wx as temporary workspace to construct the pivcol [OUT] */ + + + /* ------------------------------------------------------------------ */ + /* construct the candidate column (currently not in the front) */ + /* ------------------------------------------------------------------ */ + + /* Construct the column in Wx, Wm, using Wp for the positions: */ + /* Wm [0..cdeg_out-1] list of row indices in the column */ + /* Wx [0..cdeg_out-1] list of corresponding numerical values */ + /* Wp [0..n-1] starts as all negative, and ends that way too. */ + + cdeg_out = 0 ; + +#ifndef NDEBUG + /* check Wp */ + DEBUG4 (("COL ASSEMBLE: cdeg 0\nREDUCE COL out "ID"\n", pivcol [OUT])) ; + if (UMF_debug > 0 || MAX (n_row, n_col) < 1000) + { + for (i = 0 ; i < MAX (n_row, n_col) ; i++) + { + ASSERT (Wp [i] < 0) ; + } + } + DEBUG4 (("max_cdeg: "ID"\n", max_cdeg)) ; +#endif + + ASSERT (pivcol [OUT] >= 0 && pivcol [OUT] < n_col) ; + ASSERT (NON_PIVOTAL_COL (pivcol [OUT])) ; + + tpi = Col_tuples [pivcol [OUT]] ; + if (tpi) + { + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Col_tlen [pivcol [OUT]] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) continue ; /* element already deallocated */ + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + if (Cols [f] == EMPTY) continue ; /* column already assembled */ + ASSERT (pivcol [OUT] == Cols [f]) ; + + Rows = Cols + ep->ncols ; + nrows = ep->nrows ; + p += UNITS (Int, ep->ncols + nrows) ; + C = ((Entry *) p) + f * nrows ; + + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + if (row >= 0) /* skip this if already gone from element */ + { + ASSERT (row < n_row) ; + pos = Wp [row] ; + if (pos < 0) + { + /* new entry in the pattern - save Wp */ + ASSERT (cdeg_out < n_row) ; + if (cdeg_out >= max_cdeg) + { + /* :: pattern change (cdeg out failure) :: */ + DEBUGm4 (("cdeg out failure\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + Wp [row] = cdeg_out ; + Wm [cdeg_out] = row ; + Wx [cdeg_out++] = C [i] ; + } + else + { + /* entry already in pattern - sum the values */ + /* Wx [pos] += C [i] ; */ + ASSEMBLE (Wx [pos], C [i]) ; + } + } + } + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Col_tlen [pivcol [OUT]] = tp2 - tp1 ; + } + + /* ------------------------------------------------------------------ */ + +#ifndef NDEBUG + DEBUG4 (("Reduced column: cdeg out "ID"\n", cdeg_out)) ; + for (i = 0 ; i < cdeg_out ; i++) + { + DEBUG4 ((" "ID" "ID" "ID, i, Wm [i], Wp [Wm [i]])) ; + EDEBUG4 (Wx [i]) ; + DEBUG4 (("\n")) ; + ASSERT (i == Wp [Wm [i]]) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* new degree of pivcol [OUT] is cdeg_out */ + /* ------------------------------------------------------------------ */ + + /* search for two candidate pivot rows */ + status = UMF_row_search (Numeric, Work, Symbolic, + 0, cdeg_out, Wm, Wp, /* pattern of column to search */ + pivrow [OUT], rdeg [OUT], Woi, Woo, pivrow [IN], Wx, + pivcol [OUT], freebie) ; + + /* ------------------------------------------------------------------ */ + /* fatal error if matrix pattern has changed since symbolic analysis */ + /* ------------------------------------------------------------------ */ + + if (status == UMFPACK_ERROR_different_pattern) + { + /* :: pattern change detected in umf_local_search :: */ + return (UMFPACK_ERROR_different_pattern) ; + } + + /* ------------------------------------------------------------------ */ + /* Clear Wp */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < cdeg_out ; i++) + { + Wp [Wm [i]] = EMPTY ; /* clear Wp */ + } + + /* ------------------------------------------------------------------ */ + /* check for rectangular, singular matrix */ + /* ------------------------------------------------------------------ */ + + if (status == UMFPACK_WARNING_singular_matrix) + { + /* Pivot column is empty, and row-merge set is empty too. The + * matrix is structurally singular. The current frontal matrix must + * be empty, too. It it weren't, and pivcol [OUT] exists, then + * there would be at least one row that could be selected. Since + * the current front is empty, pivcol [IN] must also be EMPTY. + */ + + DEBUGm4 (("Note: pivcol [OUT]: "ID" discard\n", pivcol [OUT])) ; + ASSERT ((Work->fnrows == 0 && Work->fncols == 0)) ; + ASSERT (pivcol [IN] == EMPTY) ; + + /* remove the failed pivcol [OUT] from candidate set */ + ASSERT (pivcol [OUT] == Work->Candidates [jcand [OUT]]) ; + remove_candidate (jcand [OUT], Work, Symbolic) ; + Work->ndiscard++ ; + + /* delete all of the tuples, and all contributions to this column */ + DEBUG1 (("Prune tuples of dead outcol: "ID"\n", pivcol [OUT])) ; + Col_tlen [pivcol [OUT]] = 0 ; + UMF_mem_free_tail_block (Numeric, Col_tuples [pivcol [OUT]]) ; + Col_tuples [pivcol [OUT]] = 0 ; + + /* no pivot found at all */ + return (UMFPACK_WARNING_singular_matrix) ; + } + + /* ------------------------------------------------------------------ */ + + if (freebie [IN]) + { + /* the "in" row is the same as the "in" row for the "in" column */ + Woi = Fcols ; + rdeg [OUT][IN] = rdeg [IN][IN] ; + DEBUG4 (("Freebie in, row "ID"\n", pivrow [IN][IN])) ; + } + + if (freebie [OUT]) + { + /* the "out" row is the same as the "out" row for the "in" column */ + Woo = Wio ; + rdeg [OUT][OUT] = rdeg [IN][OUT] ; + DEBUG4 (("Freebie out, row "ID"\n", pivrow [IN][OUT])) ; + } + + /* ------------------------------------------------------------------ */ + /* evaluate OUT_IN option */ + /* ------------------------------------------------------------------ */ + + if (pivrow [OUT][IN] != EMPTY) + { + /* The current front would become an Lson of the new front. + * The candidate pivot row is in the current front, but the + * candidate pivot column is not. */ + + ASSERT (fnrows > 0 && fncols >= 0) ; + + did_rowmerge = (cdeg_out == 0) ; + if (did_rowmerge) + { + /* pivrow [OUT][IN] was found via row merge search */ + /* it is not (yet) in the pivot column pattern (add it now) */ + DEBUGm4 (("did row merge OUT col, IN row\n")) ; + Wm [0] = pivrow [OUT][IN] ; + CLEAR (Wx [0]) ; + cdeg_out = 1 ; + ASSERT (nr_out == EMPTY) ; + } + + nc = rdeg [OUT][IN] - fncols ; + ASSERT (nc >= 1) ; + + /* count rows not in current front */ + nr_out = 0 ; +#ifndef NDEBUG + debug_ok = FALSE ; +#endif + for (i = 0 ; i < cdeg_out ; i++) + { + row = Wm [i] ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + if (Frpos [row] < 0 || Frpos [row] >= fnrows) nr_out++ ; +#ifndef NDEBUG + /* we must see the pivot row somewhere */ + if (row == pivrow [OUT][IN]) + { + ASSERT (Frpos [row] >= 0) ; + debug_ok = TRUE ; + } +#endif + } + ASSERT (debug_ok) ; + + thiscost = + /* each column in front grows by nr_out: */ + (nr_out * fncols) + + /* new cols not affected by front: */ + ((nc-1) * (cdeg_out-1)) ; + + /* check the cost of relaxed OUT_IN amalgamation */ + + extra_rows = ((fnrows-1) + nr_out) - (cdeg_out - 1) ; + ASSERT (extra_rows >= 0) ; + ASSERT (fnrows + nr_out == extra_rows + cdeg_out) ; + extra_zeros = (nc-1) * extra_rows ; /* symbolic fill-in */ + + ASSERT (fnrows + nr_out == cdeg_out + extra_rows) ; + ASSERT (fncols + nc == rdeg [OUT][IN]) ; + + /* size of relaxed front (after pivot row removed): */ + fnrows_new [OUT][IN] = (fnrows-1) + nr_out ; + fncols_new [OUT][IN] = fncols + (nc-1) ; + relaxed_front = fnrows_new [OUT][IN] * fncols_new [OUT][IN] ; + + /* do relaxed amalgamation if the extra zeros are no more */ + /* than a fraction (default 0.25) of the relaxed front */ + /* if relax = 0: no extra zeros allowed */ + /* if relax = +inf: always amalgamate */ + if (did_rowmerge) + { + do_extend = FALSE ; + } + else + { + /* relax parameter uses a double relop, but ignore NaN case: */ + if (extra_zeros == 0) + { + do_extend = TRUE ; + } + else + { + do_extend = ((double) extra_zeros) < + (relax1 * (double) relaxed_front) ; + } + } + + if (do_extend) + { + /* count the cost of relaxed amalgamation */ + thiscost += extra_zeros ; + + DEBUG2 (("Evaluating option OUT-IN:\n")) ; + DEBUG2 ((" Work->fnzeros "ID" fnpiv "ID" nr_out "ID" nc "ID"\n", + Work->fnzeros, fnpiv, nr_out, nc)) ; + DEBUG2 (("fncols "ID" fnrows "ID"\n", fncols, fnrows)) ; + + /* determine if BLAS-3 update to be applied before extending. */ + /* update if too many zero entries accumulate in the LU block */ + fnzeros = Work->fnzeros + fnpiv * (nr_out + nc) ; + + DEBUG2 (("fnzeros "ID"\n", fnzeros)) ; + + new_LUsize = (fnpiv+1) * (fnrows + nr_out + fncols + nc) ; + + DEBUG2 (("new_LUsize "ID"\n", new_LUsize)) ; + + /* RELAX3 parameter uses a double relop, ignore NaN case: */ + do_update = fnpiv > 0 && + (((double) fnzeros) / ((double) new_LUsize)) > RELAX3 ; + DEBUG2 (("do_update "ID"\n", do_update)) + } + else + { + /* the current front would not be extended */ + do_update = fnpiv > 0 ; + fnzeros = 0 ; + DEBUG2 (("OUT-IN do_update forced true: "ID"\n", do_update)) ; + + /* The new front would be just big enough to hold the new + * pivot row and column. */ + fnrows_new [OUT][IN] = cdeg_out - 1 ; + fncols_new [OUT][IN] = rdeg [OUT][IN] - 1 ; + } + + DEBUG2 (("option OUT IN : nr "ID" nc "ID" cost "ID"("ID") relax "ID + "\n", nr_out, nc, thiscost, extra_zeros, do_extend)) ; + + if (bestcost == EMPTY || thiscost < bestcost) + { + /* this is the best option seen so far */ + Work->pivot_case = OUT_IN ; + bestcost = thiscost ; + Work->do_extend = do_extend ; + Work->do_update = do_update ; + new_fnzeros = fnzeros ; + } + } + + /* ------------------------------------------------------------------ */ + /* evaluate OUT_OUT option */ + /* ------------------------------------------------------------------ */ + + if (pivrow [OUT][OUT] != EMPTY) + { + /* Neither the candidate pivot row nor the candidate pivot column + * are in the current front. */ + + ASSERT (fnrows >= 0 && fncols >= 0) ; + + did_rowmerge = (cdeg_out == 0) ; + if (did_rowmerge) + { + /* pivrow [OUT][OUT] was found via row merge search */ + /* it is not (yet) in the pivot column pattern (add it now) */ + DEBUGm4 (("did row merge OUT col, OUT row\n")) ; + Wm [0] = pivrow [OUT][OUT] ; + CLEAR (Wx [0]) ; + cdeg_out = 1 ; + ASSERT (nr_out == EMPTY) ; + nr_out = 1 ; + } + + if (fnrows == 0 && fncols == 0) + { + /* the current front is completely empty */ + ASSERT (fnpiv == 0) ; + nc = rdeg [OUT][OUT] ; + extra_cols = 0 ; + nr_out = cdeg_out ; + extra_rows = 0 ; + extra_zeros = 0 ; + + thiscost = (nc-1) * (cdeg_out-1) ; /* new columns only */ + + /* size of new front: */ + fnrows_new [OUT][OUT] = nr_out-1 ; + fncols_new [OUT][OUT] = nc-1 ; + relaxed_front = fnrows_new [OUT][OUT] * fncols_new [OUT][OUT] ; + } + else + { + + /* count rows not in current front */ + if (nr_out == EMPTY) + { + nr_out = 0 ; +#ifndef NDEBUG + debug_ok = FALSE ; +#endif + for (i = 0 ; i < cdeg_out ; i++) + { + row = Wm [i] ; + ASSERT (row >= 0 && row < n_row) ; + ASSERT (NON_PIVOTAL_ROW (row)) ; + if (Frpos [row] < 0 || Frpos [row] >= fnrows) nr_out++ ; +#ifndef NDEBUG + /* we must see the pivot row somewhere */ + if (row == pivrow [OUT][OUT]) + { + ASSERT (Frpos [row] < 0 || Frpos [row] >= fnrows) ; + debug_ok = TRUE ; + } +#endif + } + ASSERT (debug_ok) ; + } + + /* count columns not in current front */ + nc = 0 ; +#ifndef NDEBUG + debug_ok = FALSE ; +#endif + for (i = 0 ; i < rdeg [OUT][OUT] ; i++) + { + col = Woo [i] ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + if (Fcpos [col] < 0) nc++ ; +#ifndef NDEBUG + /* we must see the pivot column somewhere */ + if (col == pivcol [OUT]) + { + ASSERT (Fcpos [col] < 0) ; + debug_ok = TRUE ; + } +#endif + } + ASSERT (debug_ok) ; + + extra_cols = (fncols + (nc-1)) - (rdeg [OUT][OUT] - 1) ; + extra_rows = (fnrows + (nr_out-1)) - (cdeg_out - 1) ; + ASSERT (extra_rows >= 0) ; + ASSERT (extra_cols >= 0) ; + extra_zeros = ((nc-1) * extra_rows) + ((nr_out-1) * extra_cols); + + ASSERT (fnrows + nr_out == cdeg_out + extra_rows) ; + ASSERT (fncols + nc == rdeg [OUT][OUT] + extra_cols) ; + + thiscost = + /* new columns: */ + ((nc-1) * (cdeg_out-1)) + + /* old columns in front grow by nr_out-1: */ + ((nr_out-1) * (fncols - extra_cols)) ; + + /* size of relaxed front: */ + fnrows_new [OUT][OUT] = fnrows + (nr_out-1) ; + fncols_new [OUT][OUT] = fncols + (nc-1) ; + relaxed_front = fnrows_new [OUT][OUT] * fncols_new [OUT][OUT] ; + + } + + /* do relaxed amalgamation if the extra zeros are no more */ + /* than a fraction (default 0.25) of the relaxed front */ + /* if relax = 0: no extra zeros allowed */ + /* if relax = +inf: always amalgamate */ + if (did_rowmerge) + { + do_extend = FALSE ; + } + else + { + /* relax parameter uses a double relop, but ignore NaN case: */ + if (extra_zeros == 0) + { + do_extend = TRUE ; + } + else + { + do_extend = ((double) extra_zeros) < + (relax1 * (double) relaxed_front) ; + } + } + + if (do_extend) + { + /* count the cost of relaxed amalgamation */ + thiscost += extra_zeros ; + + DEBUG2 (("Evaluating option OUT-OUT:\n")) ; + DEBUG2 (("Work->fnzeros "ID" fnpiv "ID" nr_out "ID" nc "ID"\n", + Work->fnzeros, fnpiv, nr_out, nc)) ; + DEBUG2 (("fncols "ID" fnrows "ID"\n", fncols, fnrows)) ; + + /* determine if BLAS-3 update to be applied before extending. */ + /* update if too many zero entries accumulate in the LU block */ + fnzeros = Work->fnzeros + fnpiv * (nr_out + nc) ; + + DEBUG2 (("fnzeros "ID"\n", fnzeros)) ; + + new_LUsize = (fnpiv+1) * (fnrows + nr_out + fncols + nc) ; + + DEBUG2 (("new_LUsize "ID"\n", new_LUsize)) ; + + /* RELAX3 parameter uses a double relop, ignore NaN case: */ + do_update = fnpiv > 0 && + (((double) fnzeros) / ((double) new_LUsize)) > RELAX3 ; + DEBUG2 (("do_update "ID"\n", do_update)) + } + else + { + /* the current front would not be extended */ + do_update = fnpiv > 0 ; + fnzeros = 0 ; + DEBUG2 (("OUT-OUT do_update forced true: "ID"\n", do_update)) ; + + /* The new front would be just big enough to hold the new + * pivot row and column. */ + fnrows_new [OUT][OUT] = cdeg_out - 1 ; + fncols_new [OUT][OUT] = rdeg [OUT][OUT] - 1 ; + } + + DEBUG2 (("option OUT OUT: nr "ID" nc "ID" cost "ID"\n", + rdeg [OUT][OUT], cdeg_out, thiscost)) ; + + if (bestcost == EMPTY || thiscost < bestcost) + { + /* this is the best option seen so far */ + Work->pivot_case = OUT_OUT ; + bestcost = thiscost ; + Work->do_extend = do_extend ; + Work->do_update = do_update ; + new_fnzeros = fnzeros ; + } + } + } + + /* At this point, a structural pivot has been found. */ + /* It may be numerically zero, however. */ + ASSERT (Work->pivot_case != EMPTY) ; + DEBUG2 (("local search, best option "ID", best cost "ID"\n", + Work->pivot_case, bestcost)) ; + + /* ====================================================================== */ + /* Pivot row and column, and extension, now determined */ + /* ====================================================================== */ + + Work->fnzeros = new_fnzeros ; + + /* ---------------------------------------------------------------------- */ + /* finalize the pivot row and column */ + /* ---------------------------------------------------------------------- */ + + switch (Work->pivot_case) + { + case IN_IN: + DEBUG2 (("IN-IN option selected\n")) ; + ASSERT (fnrows > 0 && fncols > 0) ; + Work->pivcol_in_front = TRUE ; + Work->pivrow_in_front = TRUE ; + Work->pivcol = pivcol [IN] ; + Work->pivrow = pivrow [IN][IN] ; + Work->ccdeg = nr_in ; + Work->Wrow = Fcols ; + Work->rrdeg = rdeg [IN][IN] ; + jj = jcand [IN] ; + Work->fnrows_new = fnrows_new [IN][IN] ; + Work->fncols_new = fncols_new [IN][IN] ; + break ; + + case IN_OUT: + DEBUG2 (("IN-OUT option selected\n")) ; + ASSERT (fnrows >= 0 && fncols > 0) ; + Work->pivcol_in_front = TRUE ; + Work->pivrow_in_front = FALSE ; + Work->pivcol = pivcol [IN] ; + Work->pivrow = pivrow [IN][OUT] ; + Work->ccdeg = nr_in ; + Work->Wrow = Wio ; + Work->rrdeg = rdeg [IN][OUT] ; + jj = jcand [IN] ; + Work->fnrows_new = fnrows_new [IN][OUT] ; + Work->fncols_new = fncols_new [IN][OUT] ; + break ; + + case OUT_IN: + DEBUG2 (("OUT-IN option selected\n")) ; + ASSERT (fnrows > 0 && fncols >= 0) ; + Work->pivcol_in_front = FALSE ; + Work->pivrow_in_front = TRUE ; + Work->pivcol = pivcol [OUT] ; + Work->pivrow = pivrow [OUT][IN] ; + Work->ccdeg = cdeg_out ; + /* Wrow might be equivalenced to Fcols (Freebie in): */ + Work->Wrow = Woi ; + Work->rrdeg = rdeg [OUT][IN] ; + /* Work->Wrow[0..fncols-1] is not there. See Fcols instead */ + jj = jcand [OUT] ; + Work->fnrows_new = fnrows_new [OUT][IN] ; + Work->fncols_new = fncols_new [OUT][IN] ; + break ; + + case OUT_OUT: + DEBUG2 (("OUT-OUT option selected\n")) ; + ASSERT (fnrows >= 0 && fncols >= 0) ; + Work->pivcol_in_front = FALSE ; + Work->pivrow_in_front = FALSE ; + Work->pivcol = pivcol [OUT] ; + Work->pivrow = pivrow [OUT][OUT] ; + Work->ccdeg = cdeg_out ; + /* Wrow might be equivalenced to Wio (Freebie out): */ + Work->Wrow = Woo ; + Work->rrdeg = rdeg [OUT][OUT] ; + jj = jcand [OUT] ; + Work->fnrows_new = fnrows_new [OUT][OUT] ; + Work->fncols_new = fncols_new [OUT][OUT] ; + break ; + + } + + ASSERT (IMPLIES (fnrows == 0 && fncols == 0, Work->pivot_case == OUT_OUT)) ; + + if (!Work->pivcol_in_front && pivcol [IN] != EMPTY) + { + /* clear Frpos if pivcol [IN] was searched, but not selected */ + for (i = fnrows ; i < cdeg_in ; i++) + { + Frpos [Frows [i]] = EMPTY; + } + } + + /* ---------------------------------------------------------------------- */ + /* Pivot row and column have been found */ + /* ---------------------------------------------------------------------- */ + + /* ---------------------------------------------------------------------- */ + /* remove pivot column from candidate pivot column set */ + /* ---------------------------------------------------------------------- */ + + ASSERT (jj >= 0 && jj < Work->nCandidates) ; + ASSERT (Work->pivcol == Work->Candidates [jj]) ; + remove_candidate (jj, Work, Symbolic) ; + + /* ---------------------------------------------------------------------- */ + /* check for frontal matrix growth */ + /* ---------------------------------------------------------------------- */ + + DEBUG1 (("Check frontal growth:\n")) ; + DEBUG1 (("fnrows_new "ID" + 1 = "ID", fnr_curr "ID"\n", + Work->fnrows_new, Work->fnrows_new + 1, fnr_curr)) ; + DEBUG1 (("fncols_new "ID" + 1 = "ID", fnc_curr "ID"\n", + Work->fncols_new, Work->fncols_new + 1, fnc_curr)) ; + + Work->do_grow = (Work->fnrows_new + 1 > fnr_curr + || Work->fncols_new + 1 > fnc_curr) ; + if (Work->do_grow) + { + DEBUG0 (("\nNeed to grow frontal matrix, force do_update true\n")) ; + /* If the front must grow, then apply the pending updates and remove + * the current pivot rows/columns from the front prior to growing the + * front. This frees up as much space as possible for the new front. */ + if (!Work->do_update && fnpiv > 0) + { + /* This update would not have to be done if the current front + * was big enough. */ + Work->nforced++ ; + Work->do_update = TRUE ; + } + } + + /* ---------------------------------------------------------------------- */ + /* current pivot column */ + /* ---------------------------------------------------------------------- */ + + /* + c1) If pivot column index is in the current front: + + The pivot column pattern is in Frows [0 .. fnrows-1] and + the extension is in Frows [fnrows ... fnrows+ccdeg-1]. + + Frpos [Frows [0 .. fnrows+ccdeg-1]] is + equal to 0 .. fnrows+ccdeg-1. Wm is not needed. + + The values are in Wy [0 .. fnrows+ccdeg-1]. + + c2) Otherwise, if the pivot column index is not in the current front: + + c2a) If the front is being extended, old row indices in the the + pivot column pattern are in Frows [0 .. fnrows-1]. + + All entries are in Wm [0 ... ccdeg-1], with values in + Wx [0 .. ccdeg-1]. These may include entries already in + Frows [0 .. fnrows-1]. + + Frpos [Frows [0 .. fnrows-1]] is equal to 0 .. fnrows-1. + Frpos [Wm [0 .. ccdeg-1]] for new entries is < 0. + + c2b) If the front is not being extended, then the entire pivot + column pattern is in Wm [0 .. ccdeg-1]. It includes + the pivot row index. It is does not contain the pattern + Frows [0..fnrows-1]. The intersection of these two + sets may or may not be empty. The values are in Wx [0..ccdeg-1] + + In both cases c1 and c2, Frpos [Frows [0 .. fnrows-1]] is equal + to 0 .. fnrows-1, which is the pattern of the current front. + Any entry of Frpos that is not specified above is < 0. + */ + + +#ifndef NDEBUG + DEBUG2 (("\n\nSEARCH DONE: Pivot col "ID" in: ("ID") pivot row "ID" in: ("ID + ") extend: "ID"\n\n", Work->pivcol, Work->pivcol_in_front, + Work->pivrow, Work->pivrow_in_front, Work->do_extend)) ; + UMF_dump_rowcol (1, Numeric, Work, Work->pivcol, !Symbolic->fixQ) ; + DEBUG2 (("Pivot col "ID": fnrows "ID" ccdeg "ID"\n", Work->pivcol, fnrows, + Work->ccdeg)) ; + if (Work->pivcol_in_front) /* case c1 */ + { + Int found = FALSE ; + DEBUG3 (("Pivcol in front\n")) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Frows [i] ; + DEBUG3 ((ID": row:: "ID" in front ", i, row)) ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + ASSERT (Frpos [row] == i) ; + EDEBUG3 (Wy [i]) ; + if (row == Work->pivrow) + { + DEBUG3 ((" <- pivrow")) ; + found = TRUE ; + } + DEBUG3 (("\n")) ; + } + ASSERT (found == Work->pivrow_in_front) ; + found = FALSE ; + for (i = fnrows ; i < fnrows + Work->ccdeg ; i++) + { + row = Frows [i] ; + DEBUG3 ((ID": row:: "ID" (new)", i, row)) ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + ASSERT (Frpos [row] == i) ; + EDEBUG3 (Wy [i]) ; + if (row == Work->pivrow) + { + DEBUG3 ((" <- pivrow")) ; + found = TRUE ; + } + DEBUG3 (("\n")) ; + } + ASSERT (found == !Work->pivrow_in_front) ; + } + else + { + if (Work->do_extend) + { + Int found = FALSE ; + DEBUG3 (("Pivcol not in front (extend)\n")) ; + for (i = 0 ; i < fnrows ; i++) + { + row = Frows [i] ; + DEBUG3 ((ID": row:: "ID" in front ", i, row)) ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + ASSERT (Frpos [row] == i) ; + if (row == Work->pivrow) + { + DEBUG3 ((" <- pivrow")) ; + found = TRUE ; + } + DEBUG3 (("\n")) ; + } + ASSERT (found == Work->pivrow_in_front) ; + found = FALSE ; + DEBUG3 (("----\n")) ; + for (i = 0 ; i < Work->ccdeg ; i++) + { + row = Wm [i] ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + DEBUG3 ((ID": row:: "ID" ", i, row)) ; + EDEBUG3 (Wx [i]) ; + if (Frpos [row] < 0) + { + DEBUG3 ((" (new) ")) ; + } + if (row == Work->pivrow) + { + DEBUG3 ((" <- pivrow")) ; + found = TRUE ; + /* ... */ + if (Work->pivrow_in_front) ASSERT (Frpos [row] >= 0) ; + else ASSERT (Frpos [row] < 0) ; + } + DEBUG3 (("\n")) ; + } + ASSERT (found) ; + } + else + { + Int found = FALSE ; + DEBUG3 (("Pivcol not in front (no extend)\n")) ; + for (i = 0 ; i < Work->ccdeg ; i++) + { + row = Wm [i] ; + ASSERT (row >= 0 && row < n_row && NON_PIVOTAL_ROW (row)) ; + DEBUG3 ((ID": row:: "ID" ", i, row)) ; + EDEBUG3 (Wx [i]) ; + DEBUG3 ((" (new) ")) ; + if (row == Work->pivrow) + { + DEBUG3 ((" <- pivrow")) ; + found = TRUE ; + } + DEBUG3 (("\n")) ; + } + ASSERT (found) ; + } + } +#endif + + /* ---------------------------------------------------------------------- */ + /* current pivot row */ + /* ---------------------------------------------------------------------- */ + + /* + r1) If the pivot row index is in the current front: + + The pivot row pattern is in Fcols [0..fncols-1] and the extenson is + in Wrow [fncols .. rrdeg-1]. If the pivot column is in the current + front, then Fcols and Wrow are equivalenced. + + r2) If the pivot row index is not in the current front: + + r2a) If the front is being extended, the pivot row pattern is in + Fcols [0 .. fncols-1]. New entries are in Wrow [0 .. rrdeg-1], + but these may include entries already in Fcols [0 .. fncols-1]. + + r2b) Otherwise, the pivot row pattern is Wrow [0 .. rrdeg-1]. + + Fcpos [Fcols [0..fncols-1]] is (0..fncols-1) * fnr_curr. + All other entries in Fcpos are < 0. + + These conditions are asserted below. + + ------------------------------------------------------------------------ + Other items in Work structure that are relevant: + + pivcol: the pivot column index + pivrow: the pivot column index + + rrdeg: + ccdeg: + + fnrows: the number of rows in the currnt contribution block + fncols: the number of columns in the current contribution block + + fnrows_new: the number of rows in the new contribution block + fncols_new: the number of rows in the new contribution block + + ------------------------------------------------------------------------ + */ + + +#ifndef NDEBUG + UMF_dump_rowcol (0, Numeric, Work, Work->pivrow, TRUE) ; + DEBUG2 (("Pivot row "ID":\n", Work->pivrow)) ; + if (Work->pivrow_in_front) + { + Int found = FALSE ; + for (i = 0 ; i < fncols ; i++) + { + col = Fcols [i] ; + DEBUG3 ((" col:: "ID" in front\n", col)) ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + ASSERT (Fcpos [col] == i * fnr_curr) ; + if (col == Work->pivcol) found = TRUE ; + } + ASSERT (found == Work->pivcol_in_front) ; + found = FALSE ; + ASSERT (IMPLIES (Work->pivcol_in_front, Fcols == Work->Wrow)) ; + for (i = fncols ; i < Work->rrdeg ; i++) + { + col = Work->Wrow [i] ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + ASSERT (Fcpos [col] < 0) ; + if (col == Work->pivcol) found = TRUE ; + else DEBUG3 ((" col:: "ID" (new)\n", col)) ; + } + ASSERT (found == !Work->pivcol_in_front) ; + } + else + { + if (Work->do_extend) + { + Int found = FALSE ; + for (i = 0 ; i < fncols ; i++) + { + col = Fcols [i] ; + DEBUG3 ((" col:: "ID" in front\n", col)) ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + ASSERT (Fcpos [col] == i * fnr_curr) ; + if (col == Work->pivcol) found = TRUE ; + } + ASSERT (found == Work->pivcol_in_front) ; + found = FALSE ; + for (i = 0 ; i < Work->rrdeg ; i++) + { + col = Work->Wrow [i] ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + if (Fcpos [col] >= 0) continue ; + if (col == Work->pivcol) found = TRUE ; + else DEBUG3 ((" col:: "ID" (new, extend)\n", col)) ; + } + ASSERT (found == !Work->pivcol_in_front) ; + } + else + { + Int found = FALSE ; + for (i = 0 ; i < Work->rrdeg ; i++) + { + col = Work->Wrow [i] ; + ASSERT (col >= 0 && col < n_col && NON_PIVOTAL_COL (col)) ; + if (col == Work->pivcol) found = TRUE ; + else DEBUG3 ((" col:: "ID" (all new)\n", col)) ; + } + ASSERT (found) ; + } + } +#endif + + /* ---------------------------------------------------------------------- */ + /* determine whether to do scan2-row and scan2-col */ + /* ---------------------------------------------------------------------- */ + + if (Work->do_extend) + { + Work->do_scan2row = (fncols > 0) ; + Work->do_scan2col = (fnrows > 0) ; + } + else + { + Work->do_scan2row = (fncols > 0) && Work->pivrow_in_front ; + Work->do_scan2col = (fnrows > 0) && Work->pivcol_in_front ; + } + + /* ---------------------------------------------------------------------- */ + + DEBUG2 (("LOCAL SEARCH DONE: pivot column "ID" pivot row: "ID"\n", + Work->pivcol, Work->pivrow)) ; + DEBUG2 (("do_extend: "ID"\n", Work->do_extend)) ; + DEBUG2 (("do_update: "ID"\n", Work->do_update)) ; + DEBUG2 (("do_grow: "ID"\n", Work->do_grow)) ; + + /* ---------------------------------------------------------------------- */ + /* keep track of the diagonal */ + /* ---------------------------------------------------------------------- */ + + if (Symbolic->prefer_diagonal + && Work->pivcol < Work->n_col - Symbolic->nempty_col) + { + Diagonal_map = Work->Diagonal_map ; + Diagonal_imap = Work->Diagonal_imap ; + ASSERT (Diagonal_map != (Int *) NULL) ; + ASSERT (Diagonal_imap != (Int *) NULL) ; + + row2 = Diagonal_map [Work->pivcol] ; + col2 = Diagonal_imap [Work->pivrow] ; + + if (row2 < 0) + { + /* this was an off-diagonal pivot row */ + Work->noff_diagonal++ ; + row2 = UNFLIP (row2) ; + } + + ASSERT (Diagonal_imap [row2] == Work->pivcol) ; + ASSERT (UNFLIP (Diagonal_map [col2]) == Work->pivrow) ; + + if (row2 != Work->pivrow) + { + /* swap the diagonal map to attempt to maintain symmetry later on. + * Also mark the map for col2 (via FLIP) to denote that the entry + * now on the diagonal is not the original entry on the diagonal. */ + + DEBUG0 (("Unsymmetric pivot\n")) ; + Diagonal_map [Work->pivcol] = FLIP (Work->pivrow) ; + Diagonal_imap [Work->pivrow] = Work->pivcol ; + + Diagonal_map [col2] = FLIP (row2) ; + Diagonal_imap [row2] = col2 ; + + } + ASSERT (n_row == n_col) ; +#ifndef NDEBUG + UMF_dump_diagonal_map (Diagonal_map, Diagonal_imap, Symbolic->n1, + Symbolic->n_col, Symbolic->nempty_col) ; +#endif + } + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.h b/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_local_search.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_local_search +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.c b/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.c @@ -0,0 +1,151 @@ +/* ========================================================================== */ +/* === UMF_lsolve =========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* solves Lx = b, where L is the lower triangular factor of a matrix */ +/* B is overwritten with the solution X. */ +/* Returns the floating point operation count */ + +#include "umf_internal.h" + +GLOBAL double UMF_lsolve +( + NumericType *Numeric, + Entry X [ ], /* b on input, solution x on output */ + Int Pattern [ ] /* a work array of size n */ +) +{ + Entry xk ; + Entry *xp, *Lval ; + Int k, deg, *ip, j, row, *Lpos, *Lilen, *Lip, llen, lp, newLchain, + pos, npiv, n1, *Li ; + + /* ---------------------------------------------------------------------- */ + + if (Numeric->n_row != Numeric->n_col) return (0.) ; + npiv = Numeric->npiv ; + Lpos = Numeric->Lpos ; + Lilen = Numeric->Lilen ; + Lip = Numeric->Lip ; + n1 = Numeric->n1 ; + +#ifndef NDEBUG + DEBUG4 (("Lsolve start:\n")) ; + for (j = 0 ; j < Numeric->n_row ; j++) + { + DEBUG4 (("Lsolve start "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* singletons */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + DEBUG4 (("Singleton k "ID"\n", k)) ; + xk = X [k] ; + deg = Lilen [k] ; + if (deg > 0 && IS_NONZERO (xk)) + { + lp = Lip [k] ; + Li = (Int *) (Numeric->Memory + lp) ; + lp += UNITS (Int, deg) ; + Lval = (Entry *) (Numeric->Memory + lp) ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Li [j], k)) ; + EDEBUG4 (Lval [j]) ; + DEBUG4 (("\n")) ; + /* X [Li [j]] -= xk * Lval [j] ; */ + MULT_SUB (X [Li [j]], xk, Lval [j]) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* rest of L */ + /* ---------------------------------------------------------------------- */ + + deg = 0 ; + + for (k = n1 ; k < npiv ; k++) + { + + /* ------------------------------------------------------------------ */ + /* make column of L in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + lp = Lip [k] ; + newLchain = (lp < 0) ; + if (newLchain) + { + lp = -lp ; + deg = 0 ; + DEBUG4 (("start of chain for column of L\n")) ; + } + + /* remove pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n", + k, Pattern [pos], pos)) ; + ASSERT (!newLchain) ; + ASSERT (deg > 0) ; + ASSERT (pos >= 0 && pos < deg) ; + ASSERT (Pattern [pos] == k) ; + Pattern [pos] = Pattern [--deg] ; + } + + /* concatenate the pattern */ + ip = (Int *) (Numeric->Memory + lp) ; + llen = Lilen [k] ; + for (j = 0 ; j < llen ; j++) + { + row = *ip++ ; + DEBUG4 ((" row "ID" k "ID"\n", row, k)) ; + ASSERT (row > k) ; + Pattern [deg++] = row ; + } + + /* ------------------------------------------------------------------ */ + /* use column k of L */ + /* ------------------------------------------------------------------ */ + + xk = X [k] ; + if (IS_NONZERO (xk)) + { + xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ; + EDEBUG4 (*xp) ; + DEBUG4 (("\n")) ; + /* X [Pattern [j]] -= xk * (*xp) ; */ + MULT_SUB (X [Pattern [j]], xk, *xp) ; + xp++ ; + } + } + } + +#ifndef NDEBUG + for (j = 0 ; j < Numeric->n_row ; j++) + { + DEBUG4 (("Lsolve done "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } + DEBUG4 (("Lsolve done.\n")) ; +#endif + + return (MULTSUB_FLOPS * ((double) Numeric->lnz)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.h b/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_lsolve.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL double UMF_lsolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.c b/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.c @@ -0,0 +1,225 @@ +/* ========================================================================== */ +/* === UMF_ltsolve ========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Solves L'x = b or L.'x=b, where L is the lower triangular factor of a */ +/* matrix. B is overwritten with the solution X. */ +/* Returns the floating point operation count */ + +#include "umf_internal.h" + +GLOBAL double +#ifdef CONJUGATE_SOLVE +UMF_lhsolve /* solve L'x=b (complex conjugate transpose) */ +#else +UMF_ltsolve /* solve L.'x=b (array transpose) */ +#endif +( + NumericType *Numeric, + Entry X [ ], /* b on input, solution x on output */ + Int Pattern [ ] /* a work array of size n */ +) +{ + Entry xk ; + Entry *xp, *Lval ; + Int k, deg, *ip, j, row, *Lpos, *Lilen, kstart, kend, *Lip, llen, + lp, pos, npiv, n1, *Li ; + + /* ---------------------------------------------------------------------- */ + + if (Numeric->n_row != Numeric->n_col) return (0.) ; + npiv = Numeric->npiv ; + Lpos = Numeric->Lpos ; + Lilen = Numeric->Lilen ; + Lip = Numeric->Lip ; + kstart = npiv ; + n1 = Numeric->n1 ; + +#ifndef NDEBUG + DEBUG4 (("Ltsolve start:\n")) ; + for (j = 0 ; j < Numeric->n_row ; j++) + { + DEBUG4 (("Ltsolve start "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* non-singletons */ + /* ---------------------------------------------------------------------- */ + + for (kend = npiv-1 ; kend >= n1 ; kend = kstart-1) + { + + /* ------------------------------------------------------------------ */ + /* find the start of this Lchain */ + /* ------------------------------------------------------------------ */ + + /* for (kstart = kend ; kstart >= 0 && Lip [kstart] > 0 ; kstart--) ; */ + kstart = kend ; + while (kstart >= 0 && Lip [kstart] > 0) + { + kstart-- ; + } + + /* the Lchain goes from kstart to kend */ + + /* ------------------------------------------------------------------ */ + /* scan the whole chain to find the pattern of the last column of L */ + /* ------------------------------------------------------------------ */ + + deg = 0 ; + DEBUG4 (("start of chain for column of L\n")) ; + for (k = kstart ; k <= kend ; k++) + { + ASSERT (k >= 0 && k < npiv) ; + + /* -------------------------------------------------------------- */ + /* make column k of L in Pattern [0..deg-1] */ + /* -------------------------------------------------------------- */ + + /* remove pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n", + k, Pattern [pos], pos)) ; + ASSERT (k != kstart) ; + ASSERT (deg > 0) ; + ASSERT (pos >= 0 && pos < deg) ; + ASSERT (Pattern [pos] == k) ; + Pattern [pos] = Pattern [--deg] ; + } + + /* concatenate the pattern */ + lp = Lip [k] ; + if (k == kstart) + { + lp = -lp ; + } + ASSERT (lp > 0) ; + ip = (Int *) (Numeric->Memory + lp) ; + llen = Lilen [k] ; + for (j = 0 ; j < llen ; j++) + { + row = *ip++ ; + DEBUG4 ((" row "ID" k "ID"\n", row, k)) ; + ASSERT (row > k) ; + Pattern [deg++] = row ; + } + + } + /* Pattern [0..deg-1] is now the pattern of column kend */ + + /* ------------------------------------------------------------------ */ + /* solve using this chain, in reverse order */ + /* ------------------------------------------------------------------ */ + + DEBUG4 (("Unwinding Lchain\n")) ; + for (k = kend ; k >= kstart ; k--) + { + + /* -------------------------------------------------------------- */ + /* use column k of L */ + /* -------------------------------------------------------------- */ + + ASSERT (k >= 0 && k < npiv) ; + lp = Lip [k] ; + if (k == kstart) + { + lp = -lp ; + } + ASSERT (lp > 0) ; + llen = Lilen [k] ; + xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ; + xk = X [k] ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ; + EDEBUG4 (*xp) ; + DEBUG4 (("\n")) ; + +#ifdef CONJUGATE_SOLVE + /* xk -= X [Pattern [j]] * conjugate (*xp) ; */ + MULT_SUB_CONJ (xk, X [Pattern [j]], *xp) ; +#else + /* xk -= X [Pattern [j]] * (*xp) ; */ + MULT_SUB (xk, X [Pattern [j]], *xp) ; +#endif + + xp++ ; + } + X [k] = xk ; + + /* -------------------------------------------------------------- */ + /* construct column k-1 of L */ + /* -------------------------------------------------------------- */ + + /* un-concatenate the pattern */ + deg -= llen ; + + /* add pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + DEBUG4 ((" k "ID" adding row "ID" at position "ID"\n", + k, k, pos)) ; + ASSERT (k != kstart) ; + ASSERT (pos >= 0 && pos <= deg) ; + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* singletons */ + /* ---------------------------------------------------------------------- */ + + for (k = n1 - 1 ; k >= 0 ; k--) + { + DEBUG4 (("Singleton k "ID"\n", k)) ; + deg = Lilen [k] ; + if (deg > 0) + { + xk = X [k] ; + lp = Lip [k] ; + Li = (Int *) (Numeric->Memory + lp) ; + lp += UNITS (Int, deg) ; + Lval = (Entry *) (Numeric->Memory + lp) ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Li [j], k)) ; + EDEBUG4 (Lval [j]) ; + DEBUG4 (("\n")) ; +#ifdef CONJUGATE_SOLVE + /* xk -= X [Li [j]] * conjugate (Lval [j]) ; */ + MULT_SUB_CONJ (xk, X [Li [j]], Lval [j]) ; +#else + /* xk -= X [Li [j]] * Lval [j] ; */ + MULT_SUB (xk, X [Li [j]], Lval [j]) ; +#endif + } + X [k] = xk ; + } + } + +#ifndef NDEBUG + for (j = 0 ; j < Numeric->n_row ; j++) + { + DEBUG4 (("Ltsolve done "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } + DEBUG4 (("Ltsolve done.\n")) ; +#endif + + return (MULTSUB_FLOPS * ((double) Numeric->lnz)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.h b/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_ltsolve.h @@ -0,0 +1,19 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL double UMF_ltsolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; + +GLOBAL double UMF_lhsolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.c b/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.c @@ -0,0 +1,91 @@ +/* ========================================================================== */ +/* === UMF_malloc =========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Allocate a block of n objects, each of a given size. This routine does not + handle the case when the size is 1 (allocating char's) because of potential + integer overflow. UMFPACK never does that. + Also maintains the UMFPACK malloc count. +*/ + +#include "umf_internal.h" + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) + +/* + UMF_malloc_count is a count of the objects malloc'd by UMFPACK. If you + suspect a memory leak in your program (caused by not properly destroying + the Symbolic and Numeric objects) then compile with -DUMF_MALLOC_COUNT and + check value of UMF_malloc_count. By default, UMF_MALLOC_COUNT is not + defined, and thus UMFPACK has no global variables. +*/ + +GLOBAL Int UMF_malloc_count = 0 ; + +#endif + +#ifdef UMF_TCOV_TEST +/* For exhaustive statement coverage testing only! */ +GLOBAL int umf_fail, umf_fail_lo, umf_fail_hi ; +GLOBAL int umf_realloc_fail, umf_realloc_lo, umf_realloc_hi ; +#endif + +GLOBAL void *UMF_malloc +( + Int n_objects, + size_t size_of_object +) +{ + size_t size ; + void *p ; + +#ifdef UMF_TCOV_TEST + /* For exhaustive statement coverage testing only! */ + /* Pretend to fail, to test out-of-memory conditions. */ + umf_fail-- ; + if (umf_fail <= umf_fail_hi && umf_fail >= umf_fail_lo) + { + DEBUG0 (("umf_malloc: Pretend to fail %d %d %d\n", + umf_fail, umf_fail_hi, umf_fail_lo)) ; + return ((void *) NULL) ; + } +#endif + + DEBUG0 (("UMF_malloc: ")) ; + + /* make sure that we allocate something */ + n_objects = MAX (1, n_objects) ; + + size = (size_t) n_objects ; + ASSERT (size_of_object > 1) ; + if (size > Int_MAX / size_of_object) + { + /* object is too big for integer pointer arithmetic */ + return ((void *) NULL) ; + } + size *= size_of_object ; + + /* see umf_config.h for the memory allocator selection */ + p = ALLOCATE (size) ; + + DEBUG0 ((ID"\n", (Int) p)) ; + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) + if (p) + { + /* One more object has been malloc'ed. Keep track of the count. */ + /* (purely for sanity checks). */ + UMF_malloc_count++ ; + DEBUG0 ((" successful, new malloc count: "ID"\n", UMF_malloc_count)) ; + } +#endif + + return (p) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.h b/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_malloc.h @@ -0,0 +1,20 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#ifndef _UMF_MALLOC +#define _UMF_MALLOC + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) +GLOBAL extern Int UMF_malloc_count ; +#endif + +GLOBAL void *UMF_malloc +( + Int n_objects, + size_t size_of_object +) ; + +#endif diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.c b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.c @@ -0,0 +1,82 @@ +/* ========================================================================== */ +/* === UMF_mem_alloc_element ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The UMF_mem_* routines manage the Numeric->Memory memory space. */ + +/* Allocate a nrows-by-ncols element, and initialize it. */ +/* Returns the index into Numeric->Memory if successful, or 0 on failure. */ + +#include "umf_internal.h" +#include "umf_mem_alloc_tail_block.h" + +GLOBAL Int UMF_mem_alloc_element +( + NumericType *Numeric, + Int nrows, + Int ncols, + Int **Rows, + Int **Cols, + Entry **C, + Int *size, + Element **epout +) +{ + + Element *ep ; + Unit *p ; + Int i ; + + ASSERT (Numeric != (NumericType *) NULL) ; + ASSERT (Numeric->Memory != (Unit *) NULL) ; + + *size = GET_ELEMENT_SIZE (nrows, ncols) ; + if (INT_OVERFLOW (DGET_ELEMENT_SIZE (nrows, ncols) + 1)) + { + /* :: allocate element, int overflow :: */ + return (0) ; /* problem is too large */ + } + + i = UMF_mem_alloc_tail_block (Numeric, *size) ; + (*size)++ ; + if (!i) + { + DEBUG0 (("alloc element failed - out of memory\n")) ; + return (0) ; /* out of memory */ + } + p = Numeric->Memory + i ; + + ep = (Element *) p ; + + DEBUG2 (("alloc_element done ("ID" x "ID"): p: "ID" i "ID"\n", + nrows, ncols, (Int) (p-Numeric->Memory), i)) ; + + /* Element data structure, in order: */ + p += UNITS (Element, 1) ; /* (1) Element header */ + *Cols = (Int *) p ; /* (2) col [0..ncols-1] indices */ + *Rows = *Cols + ncols ; /* (3) row [0..nrows-1] indices */ + p += UNITS (Int, ncols + nrows) ; + *C = (Entry *) p ; /* (4) C [0..nrows-1, 0..ncols-1] */ + + ep->nrows = nrows ; /* initialize the header information */ + ep->ncols = ncols ; + ep->nrowsleft = nrows ; + ep->ncolsleft = ncols ; + ep->cdeg = 0 ; + ep->rdeg = 0 ; + ep->next = EMPTY ; + + DEBUG2 (("new block size: "ID" ", GET_BLOCK_SIZE (Numeric->Memory + i))) ; + DEBUG2 (("Element size needed "ID"\n", GET_ELEMENT_SIZE (nrows, ncols))) ; + + *epout = ep ; + + /* return the offset into Numeric->Memory */ + return (i) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.h b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_element.h @@ -0,0 +1,17 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_mem_alloc_element +( + NumericType *Numeric, + Int nrows, + Int ncols, + Int **Rows, + Int **Cols, + Entry **C, + Int *size, + Element **epout +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.c b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.c @@ -0,0 +1,54 @@ +/* ========================================================================== */ +/* === UMF_mem_alloc_head_block ============================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The UMF_mem_* routines manage the Numeric->Memory memory space. */ + +/* allocate nunits from head of Numeric->Memory. No header allocated. */ +/* Returns the index into Numeric->Memory if successful, or 0 on failure. */ + +#include "umf_internal.h" + +GLOBAL Int UMF_mem_alloc_head_block +( + NumericType *Numeric, + Int nunits +) +{ + Int p, usage ; + DEBUG2 (("GET BLOCK: from head, size "ID" ", nunits)) ; + + ASSERT (Numeric != (NumericType *) NULL) ; + ASSERT (Numeric->Memory != (Unit *) NULL) ; + +#ifndef NDEBUG + if (UMF_allocfail) + { + /* pretend to fail, to test garbage_collection */ + DEBUGm2 (("UMF_mem_alloc_head_block: pretend to fail\n")) ; + UMF_allocfail = FALSE ; /* don't fail the next time */ + return (0) ; + } +#endif + + if (nunits > (Numeric->itail - Numeric->ihead)) + { + DEBUG2 ((" failed\n")) ; + return (0) ; + } + + /* return p as an offset from Numeric->Memory */ + p = Numeric->ihead ; + Numeric->ihead += nunits ; + + DEBUG2 (("p: "ID"\n", p)) ; + usage = Numeric->ihead + Numeric->tail_usage ; + Numeric->max_usage = MAX (Numeric->max_usage, usage) ; + return (p) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.h b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_head_block.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_mem_alloc_head_block +( + NumericType *Numeric, + Int nunits +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.c b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.c @@ -0,0 +1,133 @@ +/* ========================================================================== */ +/* === UMF_mem_alloc_tail_block ============================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The UMF_mem_* routines manage the Numeric->Memory memory space. */ + +#include "umf_internal.h" + +/* allocate nunits from tail of Numeric->Memory */ +/* (requires nunits+1, for header). */ +/* Returns the index into Numeric->Memory if successful, or 0 on failure. */ + +GLOBAL Int UMF_mem_alloc_tail_block +( + NumericType *Numeric, + Int nunits +) +{ + Int bigsize, usage ; + Unit *p, *pnext, *pbig ; + + ASSERT (Numeric != (NumericType *) NULL) ; + ASSERT (Numeric->Memory != (Unit *) NULL) ; + +#ifndef NDEBUG + if (UMF_allocfail) + { + /* pretend to fail, to test garbage_collection */ + DEBUGm2 (("UMF_mem_alloc_tail_block: pretend to fail\n")) ; + UMF_allocfail = FALSE ; /* don't fail the next time */ + return (0) ; + } + DEBUG2 (("UMF_mem_alloc_tail_block, size: "ID" + 1 = "ID": ", + nunits, nunits+1)) ; +#endif + + bigsize = 0 ; + pbig = (Unit *) NULL ; + + ASSERT (nunits > 0) ; /* size must be positive */ + if (Numeric->ibig != EMPTY) + { + ASSERT (Numeric->ibig > Numeric->itail) ; + ASSERT (Numeric->ibig < Numeric->size) ; + pbig = Numeric->Memory + Numeric->ibig ; + bigsize = -pbig->header.size ; + ASSERT (bigsize > 0) ; /* Numeric->ibig is free */ + ASSERT (pbig->header.prevsize >= 0) ; /* prev. is not free */ + } + + if (pbig && bigsize >= nunits) + { + + /* use the biggest block, somewhere in middle of memory */ + p = pbig ; + pnext = p + 1 + bigsize ; + /* next is in range */ + ASSERT (pnext < Numeric->Memory + Numeric->size) ; + /* prevsize of next = this size */ + ASSERT (pnext->header.prevsize == bigsize) ; + /* next is not free */ + ASSERT (pnext->header.size > 0) ; + bigsize -= nunits + 1 ; + + if (bigsize < 4) + { + /* internal fragmentation would be too small */ + /* allocate the entire free block */ + p->header.size = -p->header.size ; + DEBUG2 (("GET BLOCK: p: "ID" size: "ID", all of big: "ID" size: " + ID"\n", (Int) (p-Numeric->Memory), nunits, Numeric->ibig, + p->header.size)) ; + /* no more biggest block */ + Numeric->ibig = EMPTY ; + + } + else + { + + /* allocate just the first nunits Units of the free block */ + p->header.size = nunits ; + /* make a new free block */ + Numeric->ibig += nunits + 1 ; + pbig = Numeric->Memory + Numeric->ibig ; + pbig->header.size = -bigsize ; + pbig->header.prevsize = nunits ; + pnext->header.prevsize = bigsize ; + DEBUG2 (("GET BLOCK: p: "ID" size: "ID", some of big: "ID" left: " + ID"\n", (Int) (p-Numeric->Memory), nunits, Numeric->ibig, + bigsize)) ; + } + + } + else + { + + /* allocate from the top of tail */ + pnext = Numeric->Memory + Numeric->itail ; + DEBUG2 (("GET BLOCK: from tail ")) ; + if ((nunits + 1) > (Numeric->itail - Numeric->ihead)) + { + DEBUG2 (("\n")) ; + return (0) ; + } + Numeric->itail -= (nunits + 1) ; + p = Numeric->Memory + Numeric->itail ; + p->header.size = nunits ; + p->header.prevsize = 0 ; + pnext->header.prevsize = nunits ; + DEBUG2 (("p: "ID" size: "ID", new tail "ID"\n", + (Int) (p-Numeric->Memory), nunits, Numeric->itail)) ; + } + + Numeric->tail_usage += p->header.size + 1 ; + usage = Numeric->ihead + Numeric->tail_usage ; + Numeric->max_usage = MAX (Numeric->max_usage, usage) ; + +#ifndef NDEBUG + UMF_debug -= 10 ; + UMF_dump_memory (Numeric) ; + UMF_debug += 10 ; +#endif + + /* p points to the header. Add one to point to the usable block itself. */ + /* return the offset into Numeric->Memory */ + return ((p - Numeric->Memory) + 1) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.h b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_alloc_tail_block.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_mem_alloc_tail_block +( + NumericType *Numeric, + Int nunits +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.c b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.c @@ -0,0 +1,142 @@ +/* ========================================================================== */ +/* === UMF_mem_free_tail_block ============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The UMF_mem_* routines manage the Numeric->Memory memory space. */ + +/* free a block from the tail of Numeric->memory */ + +#include "umf_internal.h" + +GLOBAL void UMF_mem_free_tail_block +( + NumericType *Numeric, + Int i +) +{ + Unit *pprev, *pnext, *p, *pbig ; + Int sprev ; + + ASSERT (Numeric != (NumericType *) NULL) ; + ASSERT (Numeric->Memory != (Unit *) NULL) ; + if (i == EMPTY || i == 0) return ; /* already deallocated */ + + /* ---------------------------------------------------------------------- */ + /* get the block */ + /* ---------------------------------------------------------------------- */ + + p = Numeric->Memory + i ; + + p-- ; /* get the corresponding header */ + DEBUG2 (("free block: p: "ID, (Int) (p-Numeric->Memory))) ; + ASSERT (p >= Numeric->Memory + Numeric->itail) ; + ASSERT (p < Numeric->Memory + Numeric->size) ; + ASSERT (p->header.size > 0) ; /* block not already free */ + ASSERT (p->header.prevsize >= 0) ; + + Numeric->tail_usage -= p->header.size + 1 ; + + /* ---------------------------------------------------------------------- */ + /* merge with next free block, if any */ + /* ---------------------------------------------------------------------- */ + + pnext = p + 1 + p->header.size ; + DEBUG2 (("size: "ID" next: "ID" ", p->header.size, + (Int) (pnext-Numeric->Memory))) ; + ASSERT (pnext < Numeric->Memory + Numeric->size) ; + ASSERT (pnext->header.prevsize == p->header.size) ; + ASSERT (pnext->header.size != 0) ; + + if (pnext->header.size < 0) + { + /* next block is also free - merge with current block */ + p->header.size += (-(pnext->header.size)) + 1 ; + DEBUG2 ((" NEXT FREE ")) ; + } + + /* ---------------------------------------------------------------------- */ + /* merge with previous free block, if any */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + if (p == Numeric->Memory + Numeric->itail) + { + DEBUG2 ((" at top of tail ")) ; + ASSERT (p->header.prevsize == 0) ; + } +#endif + + if (p > Numeric->Memory + Numeric->itail) + { + ASSERT (p->header.prevsize > 0) ; + pprev = p - 1 - p->header.prevsize ; + DEBUG2 ((" prev: "ID" ", (Int) (pprev-Numeric->Memory))) ; + ASSERT (pprev >= Numeric->Memory + Numeric->itail) ; + sprev = pprev->header.size ; + if (sprev < 0) + { + /* previous block is also free - merge it with current block */ + ASSERT (p->header.prevsize == -sprev) ; + pprev->header.size = p->header.size + (-sprev) + 1 ; + p = pprev ; + DEBUG2 ((" PREV FREE ")) ; + /* note that p may now point to Numeric->itail */ + } +#ifndef NDEBUG + else + { + ASSERT (p->header.prevsize == sprev) ; + } +#endif + } + + /* ---------------------------------------------------------------------- */ + /* free the block, p */ + /* ---------------------------------------------------------------------- */ + + pnext = p + 1 + p->header.size ; + ASSERT (pnext < Numeric->Memory + Numeric->size) ; + + if (p == Numeric->Memory + Numeric->itail) + { + /* top block in list is freed */ + Numeric->itail = pnext - Numeric->Memory ; + pnext->header.prevsize = 0 ; + DEBUG2 ((" NEW TAIL : "ID" ", Numeric->itail)) ; + ASSERT (pnext->header.size > 0) ; + if (Numeric->ibig != EMPTY && Numeric->ibig <= Numeric->itail) + { + /* the big free block is now above the tail */ + Numeric->ibig = EMPTY ; + } + } + else + { + /* keep track of the biggest free block seen */ + if (Numeric->ibig == EMPTY) + { + Numeric->ibig = p - Numeric->Memory ; + } + else + { + pbig = Numeric->Memory + Numeric->ibig ; + if (-(pbig->header.size) < p->header.size) + { + Numeric->ibig = p - Numeric->Memory ; + } + } + /* flag the block as free, somewhere in the middle of the tail */ + pnext->header.prevsize = p->header.size ; + p->header.size = -(p->header.size) ; + } + + DEBUG2 (("new p: "ID" freesize: "ID"\n", (Int) (p-Numeric->Memory), + -(p->header.size))) ; + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.h b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_mem_free_tail_block +( + NumericType *Numeric, + Int i +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.c b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.c @@ -0,0 +1,64 @@ +/* ========================================================================== */ +/* === UMF_mem_init_memoryspace ============================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* The UMF_mem_* routines manage the Numeric->Memory memory space. */ + +#include "umf_internal.h" + +/* initialize the LU and element workspace (Numeric->Memory) */ + +GLOBAL void UMF_mem_init_memoryspace +( + NumericType *Numeric +) +{ + Unit *p ; + + ASSERT (Numeric != (NumericType *) NULL) ; + ASSERT (Numeric->Memory != (Unit *) NULL) ; + ASSERT (Numeric->size >= 3) ; + DEBUG0 (("Init memory space, size "ID"\n", Numeric->size)) ; + + Numeric->ngarbage = 0 ; + Numeric->nrealloc = 0 ; + Numeric->ncostly = 0 ; + Numeric->ibig = EMPTY ; + Numeric->ihead = 0 ; + Numeric->itail = Numeric->size ; + +#ifndef NDEBUG + UMF_allocfail = FALSE ; +#endif + + /* allocate the 2-unit tail marker block and initialize it */ + Numeric->itail -= 2 ; + p = Numeric->Memory + Numeric->itail ; + DEBUG2 (("p "ID" tail "ID"\n", (Int) (p-Numeric->Memory), Numeric->itail)) ; + Numeric->tail_usage = 2 ; + p->header.prevsize = 0 ; + p->header.size = 1 ; + + /* allocate a 1-unit head marker block at the head of memory */ + /* this is done so that an offset of zero is treated as a NULL pointer */ + Numeric->ihead++ ; + + /* initial usage in Numeric->Memory */ + Numeric->max_usage = 3 ; + Numeric->init_usage = Numeric->max_usage ; + + /* Note that UMFPACK_*symbolic ensures that Numeric->Memory is of size */ + /* at least 3, so this initialization will always succeed. */ + +#ifndef NDEBUG + DEBUG2 (("init_memoryspace, all free (except one unit at head\n")) ; + UMF_dump_memory (Numeric) ; +#endif + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.h b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_init_memoryspace.h @@ -0,0 +1,10 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_mem_init_memoryspace +( + NumericType *Numeric +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_multicompile.c b/liboctave/UMFPACK/UMFPACK/Source/umf_multicompile.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_multicompile.c @@ -0,0 +1,58 @@ +/* ========================================================================== */ +/* === UMF_multicompile ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* This file is not needed if you have the Unix/Linux "make" command for + * compiling UMFPACK. Microsoft Visual Studio cannot be configured to compile + * one file multiple times, with different -D flags. In this case, you can + * use this file instead. To use this file, see the Demo/simple_compile file. + * + * This file includes the following source files: + * + * umf_ltsolve.c + * umf_utsolve.c + * umf_triplet.c + * umf_assemble.c + * umf_store_lu.c + * umfpack_solve.c + * + * This file simply compiles the above files with different pre-#define'd flags, + * by defining the flags and then #include'ing the source files themselves. + * This is a rather unconventional approach, since by convention #include is + * supposed to be used with *.h files not *.c. However, it is one way of + * working around the limitations of Microsoft Visual Studio. + * + * You still need to compile all files separately as well, with none of the + * pre-#define'd terms listed below. + */ + +/* compile the complex conjugate forward/backsolves */ +#define CONJUGATE_SOLVE +#include "umf_ltsolve.c" +#include "umf_utsolve.c" + +/* compile umf_triplet with DO_MAP, DO_VALUES and DO_MAP, and just DO_VALUES */ +#define DO_MAP +#include "umf_triplet.c" +#define DO_VALUES +#include "umf_triplet.c" +#undef DO_MAP +#include "umf_triplet.c" + +/* compile the FIXQ version of umf_assemble */ +#define FIXQ +#include "umf_assemble.c" + +/* compile the DROP version of umf_store_lu */ +#define DROP +#include "umf_store_lu.c" + +/* compile umfpack_wsolve */ +#define WSOLVE +#include "umfpack_solve.c" diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.c b/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.c @@ -0,0 +1,75 @@ +/* ========================================================================== */ +/* === UMF_realloc ========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Realloc a block previously allocated by UMF_malloc. + Return NULL on failure (in which case the block is still allocated, and will + be kept at is present size). This routine is only used for Numeric->Memory. +*/ + +#include "umf_internal.h" + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) +#include "umf_malloc.h" +#endif + +GLOBAL void *UMF_realloc +( + void *p, + Int n_objects, + size_t size_of_object +) +{ + size_t size ; + void *p2 ; + +#ifdef UMF_TCOV_TEST + /* For exhaustive statement coverage testing only! */ + /* Pretend to fail, to test out-of-memory conditions. */ + umf_realloc_fail-- ; + if (umf_realloc_fail <= umf_realloc_hi && + umf_realloc_fail >= umf_realloc_lo) + { + return ((void *) NULL) ; + } +#endif + + /* make sure that we allocate something */ + n_objects = MAX (1, n_objects) ; + + size = (size_t) n_objects ; + ASSERT (size_of_object > 1) ; + if (size > Int_MAX / size_of_object) + { + /* :: int overflow in umf_realloc :: */ + return ((void *) NULL) ; + } + size *= size_of_object ; + + DEBUG0 (("UMF_realloc: "ID" n_objects "ID" size_of_object "ID"\n", + (Int) p, n_objects, (Int) size_of_object)) ; + + /* see umf_config.h for the memory allocator selection */ + p2 = REALLOCATE (p, size) ; + +#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG) + /* If p didn't exist on input, and p2 exists, then a new object has been + * allocated. */ + if (p == (void *) NULL && p2 != (void *) NULL) + { + UMF_malloc_count++ ; + } +#endif + + DEBUG0 (("UMF_realloc: "ID" new malloc count "ID"\n", + (Int) p2, UMF_malloc_count)) ; + + return (p2) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.h b/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_realloc.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void *UMF_realloc +( + void *p, + Int n_objects, + size_t size_of_object +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.c b/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.c @@ -0,0 +1,85 @@ +/* ========================================================================== */ +/* === UMF_report_perm ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include "umf_internal.h" + +#define PRINTF4U(params) { if (user || prl >= 4) PRINTF (params) ; } + +GLOBAL Int UMF_report_perm +( + Int n, + const Int P [ ], + Int W [ ], /* workspace of size n */ + Int prl, + Int user +) +{ + Int i, k, valid, prl1 ; + + ASSERT (prl >= 3) ; + + PRINTF4U (("permutation vector, n = "ID". ", n)) ; + + if (n <= 0) + { + PRINTF (("ERROR: length of permutation is <= 0\n\n")) ; + return (UMFPACK_ERROR_n_nonpositive) ; + } + + if (!P) + { + /* if P is (Int *) NULL, this is the identity permutation */ + PRINTF (("(not present)\n\n")) ; + return (UMFPACK_OK) ; + } + + if (!W) + { + PRINTF (("ERROR: out of memory\n\n")) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + PRINTF4 (("\n")) ; + + for (i = 0 ; i < n ; i++) + { + W [i] = TRUE ; + } + + prl1 = prl ; + for (k = 0 ; k < n ; k++) + { + i = P [k] ; + PRINTF4 ((" "ID" : "ID" ", INDEX (k), INDEX (i))) ; + valid = (i >= 0 && i < n) ; + if (valid) + { + valid = W [i] ; + W [i] = FALSE ; + } + if (!valid) + { + /* out of range or duplicate entry */ + PRINTF (("ERROR: invalid\n\n")) ; + return (UMFPACK_ERROR_invalid_permutation) ; + } + PRINTF4 (("\n")) ; + if (prl == 4 && k == 9 && n > 10) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + } + prl = prl1 ; + + PRINTF4 ((" permutation vector ")) ; + PRINTF4U (("OK\n\n")) ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.h b/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_report_perm.h @@ -0,0 +1,14 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_report_perm +( + Int n, + const Int P [ ], + Int W [ ], + Int prl, + Int user +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.c b/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.c @@ -0,0 +1,110 @@ +/* ========================================================================== */ +/* === UMF_report_vector ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include "umf_internal.h" + +/* ========================================================================== */ +/* === print_value ========================================================== */ +/* ========================================================================== */ + +PRIVATE void print_value +( + Int i, + const double Xx [ ], + const double Xz [ ], /* used for complex case only */ + Int scalar /* if true, then print real part only */ +) +{ + Entry xi ; + /* if Xz is null, then X is in "merged" format (compatible with Entry, */ + /* and ANSI C99 double _Complex type). */ + PRINTF ((" "ID" :", INDEX (i))) ; + if (scalar) + { + PRINT_SCALAR (Xx [i]) ; + } + else + { + ASSIGN (xi, Xx, Xz, i, SPLIT (Xz)) ; + PRINT_ENTRY (xi) ; + } + PRINTF (("\n")) ; +} + +/* ========================================================================== */ +/* === UMF_report_vector ==================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMF_report_vector +( + Int n, + const double Xx [ ], + const double Xz [ ], + Int prl, + Int user, + Int scalar +) +{ + Int n2, i ; + + if (user || prl >= 4) + { + PRINTF (("dense vector, n = "ID". ", n)) ; + } + + if (user) + { + if (!Xx) + { + PRINTF (("ERROR: vector not present\n\n")) ; + return (UMFPACK_ERROR_argument_missing) ; + } + if (n < 0) + { + PRINTF (("ERROR: length of vector is < 0\n\n")) ; + return (UMFPACK_ERROR_n_nonpositive) ; + } + } + + if (user || prl >= 4) + { + PRINTF4 (("\n")) ; + } + + if (prl == 4) + { + /* print level of 4 */ + n2 = MIN (10, n) ; + for (i = 0 ; i < n2 ; i++) + { + print_value (i, Xx, Xz, scalar) ; + } + if (n2 < n) + { + PRINTF ((" ...\n")) ; + print_value (n-1, Xx, Xz, scalar) ; + } + } + else if (prl > 4) + { + /* print level 4 or more */ + for (i = 0 ; i < n ; i++) + { + print_value (i, Xx, Xz, scalar) ; + } + } + + PRINTF4 ((" dense vector ")) ; + if (user || prl >= 4) + { + PRINTF (("OK\n\n")) ; + } + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.h b/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_report_vector.h @@ -0,0 +1,15 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_report_vector +( + Int n, + const double Xx [ ], + const double Xz [ ], + Int prl, + Int user, + Int scalar +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.c b/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.c @@ -0,0 +1,837 @@ +/* ========================================================================== */ +/* === UMF_row_search ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Find two candidate pivot rows in a column: the best one in the front, + and the best one not in the front. Return the two pivot row patterns and + their exact degrees. Called by UMF_local_search. + + Returns UMFPACK_OK if successful, or UMFPACK_WARNING_singular_matrix or + UMFPACK_ERROR_different_pattern if not. + +*/ + +#include "umf_internal.h" +#include "umf_row_search.h" + +GLOBAL Int UMF_row_search +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic, + Int cdeg0, /* length of column in Front */ + Int cdeg1, /* length of column outside Front */ + const Int Pattern [ ], /* pattern of column, Pattern [0..cdeg1 -1] */ + const Int Pos [ ], /* Pos [Pattern [0..cdeg1 -1]] = 0..cdeg1 -1 */ + Int pivrow [2], /* pivrow [IN] and pivrow [OUT] */ + Int rdeg [2], /* rdeg [IN] and rdeg [OUT] */ + Int W_i [ ], /* pattern of pivrow [IN], */ + /* either Fcols or Woi */ + Int W_o [ ], /* pattern of pivrow [OUT], */ + /* either Wio or Woo */ + Int prior_pivrow [2], /* the two other rows just scanned, if any */ + const Entry Wxy [ ], /* numerical values Wxy [0..cdeg1-1], + either Wx or Wy */ + + Int pivcol, /* the candidate column being searched */ + Int freebie [ ] +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double maxval, toler, toler2, value, pivot [2] ; + Int i, row, deg, col, *Frpos, fnrows, *E, j, ncols, *Cols, *Rows, + e, f, Wrpflag, *Fcpos, fncols, tpi, max_rdeg, nans_in_col, was_offdiag, + diag_row, prefer_diagonal, *Wrp, found, *Diagonal_map ; + Tuple *tp, *tpend, *tp1, *tp2 ; + Unit *Memory, *p ; + Element *ep ; + Int *Row_tuples, *Row_degree, *Row_tlen ; + +#ifndef NDEBUG + Int *Col_degree ; + DEBUG2 (("Row_search:\n")) ; + for (i = 0 ; i < cdeg1 ; i++) + { + row = Pattern [i] ; + DEBUG4 ((" row: "ID"\n", row)) ; + ASSERT (row >= 0 && row < Numeric->n_row) ; + ASSERT (i == Pos [row]) ; + } + /* If row is not in Pattern [0..cdeg1-1], then Pos [row] == EMPTY */ + if (UMF_debug > 0 || Numeric->n_row < 1000) + { + Int cnt = cdeg1 ; + DEBUG4 (("Scan all rows:\n")) ; + for (row = 0 ; row < Numeric->n_row ; row++) + { + if (Pos [row] < 0) + { + cnt++ ; + } + else + { + DEBUG4 ((" row: "ID" pos "ID"\n", row, Pos [row])) ; + } + } + ASSERT (cnt == Numeric->n_row) ; + } + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro only */ + ASSERT (pivcol >= 0 && pivcol < Work->n_col) ; + ASSERT (NON_PIVOTAL_COL (pivcol)) ; +#endif + + pivot [IN] = 0. ; + pivot [OUT] = 0. ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + Row_degree = Numeric->Rperm ; + Row_tuples = Numeric->Uip ; + Row_tlen = Numeric->Uilen ; + Wrp = Work->Wrp ; + Frpos = Work->Frpos ; + E = Work->E ; + Memory = Numeric->Memory ; + fnrows = Work->fnrows ; + + prefer_diagonal = Symbolic->prefer_diagonal ; + Diagonal_map = Work->Diagonal_map ; + + if (Diagonal_map) + { + diag_row = Diagonal_map [pivcol] ; + was_offdiag = diag_row < 0 ; + if (was_offdiag) + { + /* the "diagonal" entry in this column was permuted here by an + * earlier pivot choice. The tighter off-diagonal tolerance will + * be used instead of the symmetric tolerance. */ + diag_row = FLIP (diag_row) ; + } + ASSERT (diag_row >= 0 && diag_row < Numeric->n_row) ; + } + else + { + diag_row = EMPTY ; /* unused */ + was_offdiag = EMPTY ; /* unused */ + } + + /* pivot row degree cannot exceed max_rdeg */ + max_rdeg = Work->fncols_max ; + + /* ---------------------------------------------------------------------- */ + /* scan pivot column for candidate rows */ + /* ---------------------------------------------------------------------- */ + + maxval = 0.0 ; + nans_in_col = FALSE ; + + for (i = 0 ; i < cdeg1 ; i++) + { + APPROX_ABS (value, Wxy [i]) ; + if (SCALAR_IS_NAN (value)) + { + nans_in_col = TRUE ; + maxval = value ; + break ; + } + /* This test can now ignore the NaN case: */ + maxval = MAX (maxval, value) ; + } + + /* if maxval is zero, the matrix is numerically singular */ + + toler = Numeric->relpt * maxval ; + toler2 = Numeric->relpt2 * maxval ; + toler2 = was_offdiag ? toler : toler2 ; + + DEBUG5 (("Row_search begins [ maxval %g toler %g %g\n", + maxval, toler, toler2)) ; + if (SCALAR_IS_NAN (toler) || SCALAR_IS_NAN (toler2)) + { + nans_in_col = TRUE ; + } + + if (!nans_in_col) + { + + /* look for the diagonal entry, if it exists */ + found = FALSE ; + ASSERT (!SCALAR_IS_NAN (toler)) ; + + if (prefer_diagonal) + { + ASSERT (diag_row != EMPTY) ; + i = Pos [diag_row] ; + if (i >= 0) + { + double a ; + ASSERT (i < cdeg1) ; + ASSERT (diag_row == Pattern [i]) ; + + APPROX_ABS (a, Wxy [i]) ; + + ASSERT (!SCALAR_IS_NAN (a)) ; + ASSERT (!SCALAR_IS_NAN (toler2)) ; + + if (SCALAR_IS_NONZERO (a) && a >= toler2) + { + /* found it! */ + DEBUG3 (("Symmetric pivot: "ID" "ID"\n", pivcol, diag_row)); + found = TRUE ; + if (Frpos [diag_row] >= 0 && Frpos [diag_row] < fnrows) + { + pivrow [IN] = diag_row ; + pivrow [OUT] = EMPTY ; + } + else + { + pivrow [IN] = EMPTY ; + pivrow [OUT] = diag_row ; + } + } + } + } + + /* either no diagonal found, or we didn't look for it */ + if (!found) + { + if (cdeg0 > 0) + { + + /* this is a column in the front */ + for (i = 0 ; i < cdeg0 ; i++) + { + double a ; + APPROX_ABS (a, Wxy [i]) ; + ASSERT (!SCALAR_IS_NAN (a)) ; + ASSERT (!SCALAR_IS_NAN (toler)) ; + if (SCALAR_IS_NONZERO (a) && a >= toler) + { + row = Pattern [i] ; + deg = Row_degree [row] ; +#ifndef NDEBUG + DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n", + i, row, deg, a)) ; + UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ; +#endif + ASSERT (Frpos [row] >= 0 && Frpos [row] < fnrows) ; + ASSERT (Frpos [row] == i) ; + /* row is in the current front */ + DEBUG4 ((" in front\n")) ; + if (deg < rdeg [IN] + /* break ties by picking the largest entry: */ + || (deg == rdeg [IN] && a > pivot [IN]) + /* break ties by picking the diagonal entry: */ + /* || (deg == rdeg [IN] && row == diag_row) */ + ) + { + /* best row in front, so far */ + pivrow [IN] = row ; + rdeg [IN] = deg ; + pivot [IN] = a ; + } + } + } + for ( ; i < cdeg1 ; i++) + { + double a ; + APPROX_ABS (a, Wxy [i]) ; + ASSERT (!SCALAR_IS_NAN (a)) ; + ASSERT (!SCALAR_IS_NAN (toler)) ; + if (SCALAR_IS_NONZERO (a) && a >= toler) + { + row = Pattern [i] ; + deg = Row_degree [row] ; +#ifndef NDEBUG + DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n", + i, row, deg, a)) ; + UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ; +#endif + ASSERT (Frpos [row] == i) ; + /* row is not in the current front */ + DEBUG4 ((" NOT in front\n")) ; + if (deg < rdeg [OUT] + /* break ties by picking the largest entry: */ + || (deg == rdeg [OUT] && a > pivot [OUT]) + /* break ties by picking the diagonal entry: */ + /* || (deg == rdeg [OUT] && row == diag_row) */ + ) + { + /* best row not in front, so far */ + pivrow [OUT] = row ; + rdeg [OUT] = deg ; + pivot [OUT] = a ; + } + } + } + + } + else + { + + /* this column is not in the front */ + for (i = 0 ; i < cdeg1 ; i++) + { + double a ; + APPROX_ABS (a, Wxy [i]) ; + ASSERT (!SCALAR_IS_NAN (a)) ; + ASSERT (!SCALAR_IS_NAN (toler)) ; + if (SCALAR_IS_NONZERO (a) && a >= toler) + { + row = Pattern [i] ; + deg = Row_degree [row] ; +#ifndef NDEBUG + DEBUG6 ((ID" candidate row "ID" deg "ID" absval %g\n", + i, row, deg, a)) ; + UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ; +#endif + if (Frpos [row] >= 0 && Frpos [row] < fnrows) + { + /* row is in the current front */ + DEBUG4 ((" in front\n")) ; + if (deg < rdeg [IN] + /* break ties by picking the largest entry: */ + || (deg == rdeg [IN] && a > pivot [IN]) + /* break ties by picking the diagonal entry: */ + /* || (deg == rdeg [IN] && row == diag_row) */ + ) + { + /* best row in front, so far */ + pivrow [IN] = row ; + rdeg [IN] = deg ; + pivot [IN] = a ; + } + } + else + { + /* row is not in the current front */ + DEBUG4 ((" NOT in front\n")) ; + if (deg < rdeg [OUT] + /* break ties by picking the largest entry: */ + || (deg == rdeg[OUT] && a > pivot [OUT]) + /* break ties by picking the diagonal entry: */ + /* || (deg == rdeg[OUT] && row == diag_row) */ + ) + { + /* best row not in front, so far */ + pivrow [OUT] = row ; + rdeg [OUT] = deg ; + pivot [OUT] = a ; + } + } + } + } + } + } + } + + /* ---------------------------------------------------------------------- */ + /* NaN handling */ + /* ---------------------------------------------------------------------- */ + + /* if cdeg1 > 0 then we must have found a pivot row ... unless NaN's */ + /* exist. Try with no numerical tests if no pivot found. */ + + if (cdeg1 > 0 && pivrow [IN] == EMPTY && pivrow [OUT] == EMPTY) + { + /* cleanup for the NaN case */ + DEBUG0 (("Found a NaN in pivot column!\n")) ; + + /* grab the first entry in the pivot column, ignoring degree, */ + /* numerical stability, and symmetric preference */ + row = Pattern [0] ; + deg = Row_degree [row] ; + if (Frpos [row] >= 0 && Frpos [row] < fnrows) + { + /* row is in the current front */ + DEBUG4 ((" in front\n")) ; + pivrow [IN] = row ; + rdeg [IN] = deg ; + } + else + { + /* row is not in the current front */ + DEBUG4 ((" NOT in front\n")) ; + pivrow [OUT] = row ; + rdeg [OUT] = deg ; + } + + /* We are now guaranteed to have a pivot, no matter how broken */ + /* (non-IEEE compliant) the underlying numerical operators are. */ + /* This is particularly a problem for Microsoft compilers (they do */ + /* not handle NaN's properly). Now try to find a sparser pivot, if */ + /* possible. */ + + for (i = 1 ; i < cdeg1 ; i++) + { + row = Pattern [i] ; + deg = Row_degree [row] ; + + if (Frpos [row] >= 0 && Frpos [row] < fnrows) + { + /* row is in the current front */ + DEBUG4 ((" in front\n")) ; + if (deg < rdeg [IN] || (deg == rdeg [IN] && row == diag_row)) + { + /* best row in front, so far */ + pivrow [IN] = row ; + rdeg [IN] = deg ; + } + } + else + { + /* row is not in the current front */ + DEBUG4 ((" NOT in front\n")) ; + if (deg < rdeg [OUT] || (deg == rdeg [OUT] && row == diag_row)) + { + /* best row not in front, so far */ + pivrow [OUT] = row ; + rdeg [OUT] = deg ; + } + } + } + } + + /* We found a pivot if there are entries (even zero ones) in pivot col */ + ASSERT (IMPLIES (cdeg1 > 0, pivrow[IN] != EMPTY || pivrow[OUT] != EMPTY)) ; + + /* If there are no entries in the pivot column, then no pivot is found */ + ASSERT (IMPLIES (cdeg1 == 0, pivrow[IN] == EMPTY && pivrow[OUT] == EMPTY)) ; + + /* ---------------------------------------------------------------------- */ + /* check for singular matrix */ + /* ---------------------------------------------------------------------- */ + + if (cdeg1 == 0) + { + if (fnrows > 0) + { + /* + Get the pivrow [OUT][IN] from the current front. + The frontal matrix looks like this: + + pivcol[OUT] + | + v + x x x x 0 <- so grab this row as the pivrow [OUT][IN]. + x x x x 0 + x x x x 0 + 0 0 0 0 0 + + The current frontal matrix has some rows in it. The degree + of the pivcol[OUT] is zero. The column is empty, and the + current front does not contribute to it. + + */ + pivrow [IN] = Work->Frows [0] ; + DEBUGm4 (("Got zero pivrow[OUT][IN] "ID" from current front\n", + pivrow [IN])) ; + } + else + { + + /* + Get a pivot row from the row-merge tree, use as + pivrow [OUT][OUT]. pivrow [IN] remains EMPTY. + This can only happen if the current front is 0-by-0. + */ + + Int *Front_leftmostdesc, *Front_1strow, *Front_new1strow, row1, + row2, fleftmost, nfr, n_row, frontid ; + + ASSERT (Work->fncols == 0) ; + + Front_leftmostdesc = Symbolic->Front_leftmostdesc ; + Front_1strow = Symbolic->Front_1strow ; + Front_new1strow = Work->Front_new1strow ; + nfr = Symbolic->nfr ; + n_row = Numeric->n_row ; + frontid = Work->frontid ; + + DEBUGm4 (("Note: pivcol: "ID" is empty front "ID"\n", + pivcol, frontid)) ; +#ifndef NDEBUG + DEBUG1 (("Calling dump rowmerge\n")) ; + UMF_dump_rowmerge (Numeric, Symbolic, Work) ; +#endif + + /* Row-merge set is the non-pivotal rows in the range */ + /* Front_new1strow [Front_leftmostdesc [frontid]] to */ + /* Front_1strow [frontid+1] - 1. */ + /* If this is empty, then use the empty rows, in the range */ + /* Front_new1strow [nfr] to n_row-1. */ + /* If this too is empty, then pivrow [OUT] will be empty. */ + /* In both cases, update Front_new1strow [...]. */ + + fleftmost = Front_leftmostdesc [frontid] ; + row1 = Front_new1strow [fleftmost] ; + row2 = Front_1strow [frontid+1] - 1 ; + DEBUG1 (("Leftmost: "ID" Rows ["ID" to "ID"] srch ["ID" to "ID"]\n", + fleftmost, Front_1strow [frontid], row2, row1, row2)) ; + + /* look in the range row1 ... row2 */ + for (row = row1 ; row <= row2 ; row++) + { + DEBUG3 ((" Row: "ID"\n", row)) ; + if (NON_PIVOTAL_ROW (row)) + { + /* found it */ + DEBUG3 ((" Row: "ID" found\n", row)) ; + ASSERT (Frpos [row] == EMPTY) ; + pivrow [OUT] = row ; + DEBUGm4 (("got row merge pivrow %d\n", pivrow [OUT])) ; + break ; + } + } + Front_new1strow [fleftmost] = row ; + + if (pivrow [OUT] == EMPTY) + { + /* not found, look in empty row set in "dummy" front */ + row1 = Front_new1strow [nfr] ; + row2 = n_row-1 ; + DEBUG3 (("Empty: "ID" Rows ["ID" to "ID"] srch["ID" to "ID"]\n", + nfr, Front_1strow [nfr], row2, row1, row2)) ; + + /* look in the range row1 ... row2 */ + for (row = row1 ; row <= row2 ; row++) + { + DEBUG3 ((" Empty Row: "ID"\n", row)) ; + if (NON_PIVOTAL_ROW (row)) + { + /* found it */ + DEBUG3 ((" Empty Row: "ID" found\n", row)) ; + ASSERT (Frpos [row] == EMPTY) ; + pivrow [OUT] = row ; + DEBUGm4 (("got dummy row pivrow %d\n", pivrow [OUT])) ; + break ; + } + } + Front_new1strow [nfr] = row ; + } + + if (pivrow [OUT] == EMPTY) + { + /* Row-merge set is empty. We can just discard */ + /* the candidate pivot column. */ + DEBUG0 (("Note: row-merge set empty\n")) ; + DEBUGm4 (("got no pivrow \n")) ; + return (UMFPACK_WARNING_singular_matrix) ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* construct the candidate row in the front, if any */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + /* check Wrp */ + ASSERT (Work->Wrpflag > 0) ; + if (UMF_debug > 0 || Work->n_col < 1000) + { + for (i = 0 ; i < Work->n_col ; i++) + { + ASSERT (Wrp [i] < Work->Wrpflag) ; + } + } +#endif + +#ifndef NDEBUG + DEBUG4 (("pivrow [IN]: "ID"\n", pivrow [IN])) ; + UMF_dump_rowcol (0, Numeric, Work, pivrow [IN], TRUE) ; +#endif + + if (pivrow [IN] != EMPTY) + { + + /* the row merge candidate row is not pivrow [IN] */ + freebie [IN] = (pivrow [IN] == prior_pivrow [IN]) && (cdeg1 > 0) ; + ASSERT (cdeg1 >= 0) ; + + if (!freebie [IN]) + { + /* include current front in the degree of this row */ + + Fcpos = Work->Fcpos ; + fncols = Work->fncols ; + + Wrpflag = Work->Wrpflag ; + + /* -------------------------------------------------------------- */ + /* construct the pattern of the IN row */ + /* -------------------------------------------------------------- */ + +#ifndef NDEBUG + /* check Fcols */ + DEBUG5 (("ROW ASSEMBLE: rdeg "ID"\nREDUCE ROW "ID"\n", + fncols, pivrow [IN])) ; + for (j = 0 ; j < fncols ; j++) + { + col = Work->Fcols [j] ; + ASSERT (col >= 0 && col < Work->n_col) ; + ASSERT (Fcpos [col] >= 0) ; + } + if (UMF_debug > 0 || Work->n_col < 1000) + { + Int cnt = fncols ; + for (col = 0 ; col < Work->n_col ; col++) + { + if (Fcpos [col] < 0) cnt++ ; + } + ASSERT (cnt == Work->n_col) ; + } +#endif + + rdeg [IN] = fncols ; + + ASSERT (pivrow [IN] >= 0 && pivrow [IN] < Work->n_row) ; + ASSERT (NON_PIVOTAL_ROW (pivrow [IN])) ; + + /* add the pivot column itself */ + ASSERT (Wrp [pivcol] != Wrpflag) ; + if (Fcpos [pivcol] < 0) + { + DEBUG3 (("Adding pivot col to pivrow [IN] pattern\n")) ; + if (rdeg [IN] >= max_rdeg) + { + /* :: pattern change (in) :: */ + return (UMFPACK_ERROR_different_pattern) ; + } + Wrp [pivcol] = Wrpflag ; + W_i [rdeg [IN]++] = pivcol ; + } + + tpi = Row_tuples [pivrow [IN]] ; + if (tpi) + { + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Row_tlen [pivrow [IN]] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) + { + continue ; /* element already deallocated */ + } + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + ncols = ep->ncols ; + Rows = Cols + ncols ; + if (Rows [f] == EMPTY) + { + continue ; /* row already assembled */ + } + ASSERT (pivrow [IN] == Rows [f]) ; + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + ASSERT (col >= EMPTY && col < Work->n_col) ; + if ((col >= 0) && (Wrp [col] != Wrpflag) + && Fcpos [col] <0) + { + ASSERT (NON_PIVOTAL_COL (col)) ; + if (rdeg [IN] >= max_rdeg) + { + /* :: pattern change (rdeg in failure) :: */ + DEBUGm4 (("rdeg [IN] >= max_rdeg failure\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + Wrp [col] = Wrpflag ; + W_i [rdeg [IN]++] = col ; + } + } + + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Row_tlen [pivrow [IN]] = tp2 - tp1 ; + } + +#ifndef NDEBUG + DEBUG4 (("Reduced IN row:\n")) ; + for (j = 0 ; j < fncols ; j++) + { + DEBUG6 ((" "ID" "ID" "ID"\n", + j, Work->Fcols [j], Fcpos [Work->Fcols [j]])) ; + ASSERT (Fcpos [Work->Fcols [j]] >= 0) ; + } + for (j = fncols ; j < rdeg [IN] ; j++) + { + DEBUG6 ((" "ID" "ID" "ID"\n", j, W_i [j], Wrp [W_i [j]])); + ASSERT (W_i [j] >= 0 && W_i [j] < Work->n_col) ; + ASSERT (Wrp [W_i [j]] == Wrpflag) ; + } + /* mark the end of the pattern in case we scan it by mistake */ + /* Note that this means W_i must be of size >= fncols_max + 1 */ + W_i [rdeg [IN]] = EMPTY ; +#endif + + /* rdeg [IN] is now the exact degree of the IN row */ + + /* clear Work->Wrp. */ + Work->Wrpflag++ ; + /* All Wrp [0..n_col] is now < Wrpflag */ + } + } + +#ifndef NDEBUG + /* check Wrp */ + if (UMF_debug > 0 || Work->n_col < 1000) + { + for (i = 0 ; i < Work->n_col ; i++) + { + ASSERT (Wrp [i] < Work->Wrpflag) ; + } + } +#endif + + /* ---------------------------------------------------------------------- */ + /* construct the candidate row not in the front, if any */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG4 (("pivrow [OUT]: "ID"\n", pivrow [OUT])) ; + UMF_dump_rowcol (0, Numeric, Work, pivrow [OUT], TRUE) ; +#endif + + /* If this is a candidate row from the row merge set, force it to be */ + /* scanned (ignore prior_pivrow [OUT]). */ + + if (pivrow [OUT] != EMPTY) + { + freebie [OUT] = (pivrow [OUT] == prior_pivrow [OUT]) && cdeg1 > 0 ; + ASSERT (cdeg1 >= 0) ; + + if (!freebie [OUT]) + { + + Wrpflag = Work->Wrpflag ; + + /* -------------------------------------------------------------- */ + /* construct the pattern of the row */ + /* -------------------------------------------------------------- */ + + rdeg [OUT] = 0 ; + + ASSERT (pivrow [OUT] >= 0 && pivrow [OUT] < Work->n_row) ; + ASSERT (NON_PIVOTAL_ROW (pivrow [OUT])) ; + + /* add the pivot column itself */ + ASSERT (Wrp [pivcol] != Wrpflag) ; + DEBUG3 (("Adding pivot col to pivrow [OUT] pattern\n")) ; + if (rdeg [OUT] >= max_rdeg) + { + /* :: pattern change (out) :: */ + return (UMFPACK_ERROR_different_pattern) ; + } + Wrp [pivcol] = Wrpflag ; + W_o [rdeg [OUT]++] = pivcol ; + + tpi = Row_tuples [pivrow [OUT]] ; + if (tpi) + { + tp = (Tuple *) (Memory + tpi) ; + tp1 = tp ; + tp2 = tp ; + tpend = tp + Row_tlen [pivrow [OUT]] ; + for ( ; tp < tpend ; tp++) + { + e = tp->e ; + ASSERT (e > 0 && e <= Work->nel) ; + if (!E [e]) + { + continue ; /* element already deallocated */ + } + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + ncols = ep->ncols ; + Rows = Cols + ncols ; + if (Rows [f] == EMPTY) + { + continue ; /* row already assembled */ + } + ASSERT (pivrow [OUT] == Rows [f]) ; + + for (j = 0 ; j < ncols ; j++) + { + col = Cols [j] ; + ASSERT (col >= EMPTY && col < Work->n_col) ; + if ((col >= 0) && (Wrp [col] != Wrpflag)) + { + ASSERT (NON_PIVOTAL_COL (col)) ; + if (rdeg [OUT] >= max_rdeg) + { + /* :: pattern change (rdeg out failure) :: */ + DEBUGm4 (("rdeg [OUT] failure\n")) ; + return (UMFPACK_ERROR_different_pattern) ; + } + Wrp [col] = Wrpflag ; + W_o [rdeg [OUT]++] = col ; + } + } + *tp2++ = *tp ; /* leave the tuple in the list */ + } + Row_tlen [pivrow [OUT]] = tp2 - tp1 ; + } + +#ifndef NDEBUG + DEBUG4 (("Reduced row OUT:\n")) ; + for (j = 0 ; j < rdeg [OUT] ; j++) + { + DEBUG6 ((" "ID" "ID" "ID"\n", j, W_o [j], Wrp [W_o [j]])) ; + ASSERT (W_o [j] >= 0 && W_o [j] < Work->n_col) ; + ASSERT (Wrp [W_o [j]] == Wrpflag) ; + } + /* mark the end of the pattern in case we scan it by mistake */ + /* Note that this means W_o must be of size >= fncols_max + 1 */ + W_o [rdeg [OUT]] = EMPTY ; +#endif + + /* rdeg [OUT] is now the exact degree of the row */ + + /* clear Work->Wrp. */ + Work->Wrpflag++ ; + /* All Wrp [0..n] is now < Wrpflag */ + + } + + } + DEBUG5 (("Row_search end ] \n")) ; + +#ifndef NDEBUG + /* check Wrp */ + if (UMF_debug > 0 || Work->n_col < 1000) + { + for (i = 0 ; i < Work->n_col ; i++) + { + ASSERT (Wrp [i] < Work->Wrpflag) ; + } + } +#endif + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.h b/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_row_search.h @@ -0,0 +1,32 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_row_search +( + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic, + Int cdeg0, + Int cdeg1, + const Int Pattern [ ], + const Int Pos [ ], + Int pivrow [2], + Int rdeg [2], + Int W_i [ ], + Int W_o [ ], + Int prior_pivrow [2], + const Entry Wxy [ ], + Int pivcol, + Int freebie [2] +) ; + +#define IN 0 +#define OUT 1 + +#define IN_IN 0 +#define IN_OUT 1 +#define OUT_IN 2 +#define OUT_OUT 3 diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_scale.c b/liboctave/UMFPACK/UMFPACK/Source/umf_scale.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_scale.c @@ -0,0 +1,127 @@ +/* ========================================================================== */ +/* === UMF_scale ============================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Divide a vector of stride 1 by the pivot value. */ + +#include "umf_internal.h" + +GLOBAL void UMF_scale +( + Int n, + Entry pivot, + Entry X [ ] +) +{ + Entry x ; + double s ; + Int i ; + + /* ---------------------------------------------------------------------- */ + /* compute the approximate absolute value of the pivot, and select method */ + /* ---------------------------------------------------------------------- */ + + APPROX_ABS (s, pivot) ; + + if (s < RECIPROCAL_TOLERANCE || IS_NAN (pivot)) + { + /* ------------------------------------------------------------------ */ + /* tiny, or zero, pivot case */ + /* ------------------------------------------------------------------ */ + + /* The pivot is tiny, or NaN. Do not divide zero by the pivot value, + * and do not multiply by 1/pivot, either. */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] /= pivot ; */ + x = X [i] ; + +#ifndef NO_DIVIDE_BY_ZERO + if (IS_NONZERO (x)) + { + DIV (X [i], x, pivot) ; + } +#else + /* Do not divide by zero */ + if (IS_NONZERO (x) && IS_NONZERO (pivot)) + { + DIV (X [i], x, pivot) ; + } +#endif + + } + + } + else + { + + /* ------------------------------------------------------------------ */ + /* normal case. select the x/pivot or x * (1/pivot) method */ + /* ------------------------------------------------------------------ */ + + /* The pivot is not tiny, and is not NaN. Don't bother to check for + * zeros in the pivot column, X. */ + +#if !defined (NRECIPROCAL) && !(defined (__GNUC__) && defined (COMPLEX)) + + /* -------------------------------------------------------------- */ + /* multiply x by (1/pivot) */ + /* -------------------------------------------------------------- */ + + /* Slightly less accurate, but faster. It allows the use of + * the level-1 BLAS dscal or zscal routine. This not used when + * UMFPACK is used in MATLAB (either as a built-in routine, or as + * a mexFunction). + * + * Using gcc version 3.2 can cause the following code to fail for + * some complex matrices (not all), with or without the BLAS. This + * was found in Red Hat Linux 7.3 on a Dell Latitude C840 with a + * Pentium 4M. Thus, this code is not used when gcc is used, for + * the complex case. + * + * It works just fine with Intel's icc compiler, version 7.0. + */ + + /* pivot = 1 / pivot */ + RECIPROCAL (pivot) ; + +#if defined (USE_NO_BLAS) + for (i = 0 ; i < n ; i++) + { + /* X [i] *= pivot ; */ + x = X [i] ; + MULT (X [i], x, pivot) ; + } +#else + BLAS_SCAL (n, pivot, X) ; +#endif + +#else + + /* -------------------------------------------------------------- */ + /* divide x by the pivot */ + /* -------------------------------------------------------------- */ + + /* This is slightly more accurate, particularly if the pivot column + * consists of only IEEE subnormals. Always do this if UMFPACK is + * being compiled as a built-in routine or mexFunction in MATLAB, + * or if gcc is being used with complex matrices. */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] /= pivot ; */ + x = X [i] ; + DIV (X [i], x, pivot) ; + } + +#endif + + } +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_scale.h b/liboctave/UMFPACK/UMFPACK/Source/umf_scale.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_scale.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_scale +( + Int n, + Entry alpha, + Entry X [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.c b/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.c @@ -0,0 +1,433 @@ +/* ========================================================================== */ +/* === UMF_scale_column ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Scale the current pivot column, move the pivot row and column into place, + and log the permutation. +*/ + +#include "umf_internal.h" +#include "umf_mem_free_tail_block.h" +#include "umf_scale.h" + +/* ========================================================================== */ +/* === shift_pivot_row ====================================================== */ +/* ========================================================================== */ + +/* Except for the BLAS, most of the time is typically spent in the following + * shift_pivot_row routine. It copies the pivot row into the U block, and + * then fills in the whole in the C block by shifting the last row of C into + * the row vacated by the pivot row. + */ + +PRIVATE void shift_pivot_row (Entry *Fd, Entry *Fs, Entry *Fe, Int len, Int d) +{ + Int j ; +#pragma ivdep + for (j = 0 ; j < len ; j++) + { + Fd [j] = Fs [j*d] ; + Fs [j*d] = Fe [j*d] ; + } +} + +/* ========================================================================== */ +/* === UMF_scale_column ===================================================== */ +/* ========================================================================== */ + +GLOBAL void UMF_scale_column +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry pivot_value ; + Entry *Fcol, *Flublock, *Flblock, *Fublock, *Fcblock ; + Int k, k1, fnr_curr, fnrows, fncols, *Frpos, *Fcpos, pivrow, pivcol, + *Frows, *Fcols, fnc_curr, fnpiv, *Row_tuples, nb, + *Col_tuples, *Rperm, *Cperm, fspos, col2, row2 ; +#ifndef NDEBUG + Int *Col_degree, *Row_degree ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + fnrows = Work->fnrows ; + fncols = Work->fncols ; + fnpiv = Work->fnpiv ; + + /* ---------------------------------------------------------------------- */ + + Rperm = Numeric->Rperm ; + Cperm = Numeric->Cperm ; + + /* ---------------------------------------------------------------------- */ + + Flublock = Work->Flublock ; + Flblock = Work->Flblock ; + Fublock = Work->Fublock ; + Fcblock = Work->Fcblock ; + + fnr_curr = Work->fnr_curr ; + fnc_curr = Work->fnc_curr ; + Frpos = Work->Frpos ; + Fcpos = Work->Fcpos ; + Frows = Work->Frows ; + Fcols = Work->Fcols ; + pivrow = Work->pivrow ; + pivcol = Work->pivcol ; + + ASSERT (pivrow >= 0 && pivrow < Work->n_row) ; + ASSERT (pivcol >= 0 && pivcol < Work->n_col) ; + +#ifndef NDEBUG + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ +#endif + + Row_tuples = Numeric->Uip ; + Col_tuples = Numeric->Lip ; + nb = Work->nb ; + +#ifndef NDEBUG + ASSERT (fnrows == Work->fnrows_new + 1) ; + ASSERT (fncols == Work->fncols_new + 1) ; + DEBUG1 (("SCALE COL: fnrows "ID" fncols "ID"\n", fnrows, fncols)) ; + DEBUG2 (("\nFrontal matrix, including all space:\n" + "fnr_curr "ID" fnc_curr "ID" nb "ID"\n" + "fnrows "ID" fncols "ID" fnpiv "ID"\n", + fnr_curr, fnc_curr, nb, fnrows, fncols, fnpiv)) ; + DEBUG2 (("\nJust the active part:\n")) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Fcblock, fnr_curr, fnrows, fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Flblock, fnr_curr, fnrows, fnpiv); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Fublock, fnc_curr, fncols, fnpiv) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Flublock, nb, fnpiv, fnpiv) ; +#endif + + /* ====================================================================== */ + /* === Shift pivot row and column ======================================= */ + /* ====================================================================== */ + + /* ---------------------------------------------------------------------- */ + /* move pivot column into place */ + /* ---------------------------------------------------------------------- */ + + /* Note that the pivot column is already in place. Just shift the last + * column into the position vacated by the pivot column. */ + + fspos = Fcpos [pivcol] ; + + /* one less column in the contribution block */ + fncols = --(Work->fncols) ; + + if (fspos != fncols * fnr_curr) + { + + Int fs = fspos / fnr_curr ; + + DEBUG6 (("Shift pivot column in front\n")) ; + DEBUG6 (("fspos: "ID" flpos: "ID"\n", fspos, fncols * fnr_curr)) ; + + /* ------------------------------------------------------------------ */ + /* move Fe => Fs */ + /* ------------------------------------------------------------------ */ + + /* column of the contribution block: */ + { + /* Fs: current position of pivot column in contribution block */ + /* Fe: position of last column in contribution block */ + Int i ; + Entry *Fs, *Fe ; + Fs = Fcblock + fspos ; + Fe = Fcblock + fncols * fnr_curr ; +#pragma ivdep + for (i = 0 ; i < fnrows ; i++) + { + Fs [i] = Fe [i] ; + } + } + + /* column of the U2 block */ + { + /* Fs: current position of pivot column in U block */ + /* Fe: last column in U block */ + Int i ; + Entry *Fs, *Fe ; + Fs = Fublock + fs ; + Fe = Fublock + fncols ; +#pragma ivdep + for (i = 0 ; i < fnpiv ; i++) + { + Fs [i * fnc_curr] = Fe [i * fnc_curr] ; + } + } + + /* move column Fe to Fs in the Fcols pattern */ + col2 = Fcols [fncols] ; + Fcols [fs] = col2 ; + Fcpos [col2] = fspos ; + } + + /* pivot column is no longer in the frontal matrix */ + Fcpos [pivcol] = EMPTY ; + +#ifndef NDEBUG + DEBUG2 (("\nFrontal matrix after col swap, including all space:\n" + "fnr_curr "ID" fnc_curr "ID" nb "ID"\n" + "fnrows "ID" fncols "ID" fnpiv "ID"\n", + fnr_curr, fnc_curr, nb, + fnrows, fncols, fnpiv)) ; + DEBUG2 (("\nJust the active part:\n")) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Fcblock, fnr_curr, fnrows, fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Flblock, fnr_curr, fnrows, fnpiv+1); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Fublock, fnc_curr, fncols, fnpiv) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Flublock, nb, fnpiv, fnpiv+1) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* move pivot row into place */ + /* ---------------------------------------------------------------------- */ + + fspos = Frpos [pivrow] ; + + /* one less row in the contribution block */ + fnrows = --(Work->fnrows) ; + + DEBUG6 (("Swap/shift pivot row in front:\n")) ; + DEBUG6 (("fspos: "ID" flpos: "ID"\n", fspos, fnrows)) ; + + if (fspos == fnrows) + { + + /* ------------------------------------------------------------------ */ + /* move Fs => Fd */ + /* ------------------------------------------------------------------ */ + + DEBUG6 (("row case 1\n")) ; + + /* row of the contribution block: */ + { + Int j ; + Entry *Fd, *Fs ; + Fd = Fublock + fnpiv * fnc_curr ; + Fs = Fcblock + fspos ; +#pragma ivdep + for (j = 0 ; j < fncols ; j++) + { + Fd [j] = Fs [j * fnr_curr] ; + } + } + + /* row of the L2 block: */ + if (Work->pivrow_in_front) + { + Int j ; + Entry *Fd, *Fs ; + Fd = Flublock + fnpiv ; + Fs = Flblock + fspos ; +#pragma ivdep + for (j = 0 ; j <= fnpiv ; j++) + { + Fd [j * nb] = Fs [j * fnr_curr] ; + } + } + else + { + Int j ; + Entry *Fd, *Fs ; + Fd = Flublock + fnpiv ; + Fs = Flblock + fspos ; +#pragma ivdep + for (j = 0 ; j < fnpiv ; j++) + { + ASSERT (IS_ZERO (Fs [j * fnr_curr])) ; + CLEAR (Fd [j * nb]) ; + } + Fd [fnpiv * nb] = Fs [fnpiv * fnr_curr] ; + } + } + else + { + + /* ------------------------------------------------------------------ */ + /* move Fs => Fd */ + /* move Fe => Fs */ + /* ------------------------------------------------------------------ */ + + DEBUG6 (("row case 2\n")) ; + /* this is the most common case, by far */ + + /* row of the contribution block: */ + { + /* Fd: destination of pivot row on U block */ + /* Fs: current position of pivot row in contribution block */ + /* Fe: position of last row in contribution block */ + Entry *Fd, *Fs, *Fe ; + Fd = Fublock + fnpiv * fnc_curr ; + Fs = Fcblock + fspos ; + Fe = Fcblock + fnrows ; + shift_pivot_row (Fd, Fs, Fe, fncols, fnr_curr) ; + } + + /* row of the L2 block: */ + if (Work->pivrow_in_front) + { + /* Fd: destination of pivot row in LU block */ + /* Fs: current position of pivot row in L block */ + /* Fe: last row in L block */ + Int j ; + Entry *Fd, *Fs, *Fe ; + Fd = Flublock + fnpiv ; + Fs = Flblock + fspos ; + Fe = Flblock + fnrows ; +#pragma ivdep + for (j = 0 ; j <= fnpiv ; j++) + { + Fd [j * nb] = Fs [j * fnr_curr] ; + Fs [j * fnr_curr] = Fe [j * fnr_curr] ; + } + } + else + { + Int j ; + Entry *Fd, *Fs, *Fe ; + Fd = Flublock + fnpiv ; + Fs = Flblock + fspos ; + Fe = Flblock + fnrows ; +#pragma ivdep + for (j = 0 ; j < fnpiv ; j++) + { + ASSERT (IS_ZERO (Fs [j * fnr_curr])) ; + CLEAR (Fd [j * nb]) ; + Fs [j * fnr_curr] = Fe [j * fnr_curr] ; + } + Fd [fnpiv * nb] = Fs [fnpiv * fnr_curr] ; + Fs [fnpiv * fnr_curr] = Fe [fnpiv * fnr_curr] ; + } + + /* move row Fe to Fs in the Frows pattern */ + row2 = Frows [fnrows] ; + Frows [fspos] = row2 ; + Frpos [row2] = fspos ; + + } + /* pivot row is no longer in the frontal matrix */ + Frpos [pivrow] = EMPTY ; + +#ifndef NDEBUG + DEBUG2 (("\nFrontal matrix after row swap, including all space:\n" + "fnr_curr "ID" fnc_curr "ID" nb "ID"\n" + "fnrows "ID" fncols "ID" fnpiv "ID"\n", + Work->fnr_curr, Work->fnc_curr, Work->nb, + Work->fnrows, Work->fncols, Work->fnpiv)) ; + DEBUG2 (("\nJust the active part:\n")) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Fcblock, fnr_curr, fnrows, fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Flblock, fnr_curr, fnrows, fnpiv+1); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Fublock, fnc_curr, fncols, fnpiv+1) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Flublock, nb, fnpiv+1, fnpiv+1) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* Frpos [row] >= 0 for each row in pivot column pattern. */ + /* offset into pattern is given by: */ + /* Frpos [row] == offset - 1 */ + /* Frpos [pivrow] is EMPTY */ + + /* Fcpos [col] >= 0 for each col in pivot row pattern. */ + /* Fcpos [col] == (offset - 1) * fnr_curr */ + /* Fcpos [pivcol] is EMPTY */ + + /* Fcols [0..fncols-1] is the pivot row pattern (excl pivot cols) */ + /* Frows [0..fnrows-1] is the pivot col pattern (excl pivot rows) */ + + /* ====================================================================== */ + /* === scale pivot column =============================================== */ + /* ====================================================================== */ + + /* pivot column (except for pivot entry itself) */ + Fcol = Flblock + fnpiv * fnr_curr ; + /* fnpiv-th pivot in frontal matrix located in Flublock (fnpiv, fnpiv) */ + pivot_value = Flublock [fnpiv + fnpiv * nb] ; + + /* this is the kth global pivot */ + k = Work->npiv + fnpiv ; + + DEBUG4 (("Pivot value: ")) ; + EDEBUG4 (pivot_value) ; + DEBUG4 (("\n")) ; + + UMF_scale (fnrows, pivot_value, Fcol) ; + + /* ---------------------------------------------------------------------- */ + /* deallocate the pivot row and pivot column tuples */ + /* ---------------------------------------------------------------------- */ + + UMF_mem_free_tail_block (Numeric, Row_tuples [pivrow]) ; + UMF_mem_free_tail_block (Numeric, Col_tuples [pivcol]) ; + + Row_tuples [pivrow] = 0 ; + Col_tuples [pivcol] = 0 ; + + DEBUG5 (("number of pivots prior to this one: "ID"\n", k)) ; + ASSERT (NON_PIVOTAL_ROW (pivrow)) ; + ASSERT (NON_PIVOTAL_COL (pivcol)) ; + + /* save row and column inverse permutation */ + k1 = ONES_COMPLEMENT (k) ; + Rperm [pivrow] = k1 ; /* aliased with Row_degree */ + Cperm [pivcol] = k1 ; /* aliased with Col_degree */ + + ASSERT (!NON_PIVOTAL_ROW (pivrow)) ; + ASSERT (!NON_PIVOTAL_COL (pivcol)) ; + + /* ---------------------------------------------------------------------- */ + /* Keep track of the pivot order. This is the kth pivot row and column. */ + /* ---------------------------------------------------------------------- */ + + /* keep track of pivot rows and columns in the LU, L, and U blocks */ + ASSERT (fnpiv < MAXNB) ; + Work->Pivrow [fnpiv] = pivrow ; + Work->Pivcol [fnpiv] = pivcol ; + + /* ====================================================================== */ + /* === one step in the factorization is done ============================ */ + /* ====================================================================== */ + + /* One more step is done, except for pending updates to the U and C blocks + * of this frontal matrix. Those are saved up, and applied by + * UMF_blas3_update when enough pivots have accumulated. Also, the + * LU factors for these pending pivots have not yet been stored. */ + + Work->fnpiv++ ; + +#ifndef NDEBUG + DEBUG7 (("Current frontal matrix: (after pivcol scale)\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.h b/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_scale_column.h @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_scale_column +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.c b/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.c @@ -0,0 +1,133 @@ +/* ========================================================================== */ +/* === UMF_set_stats ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Sets statistics in Info array. Calculates everything in double precision, + rather than Int or size_t, so that usage estimates can be computed even if + the problem is so large that it would cause integer overflow. + + This routine has many double relop's, but the NaN case is ignored. +*/ + +#include "umf_internal.h" +#include "umf_symbolic_usage.h" + +GLOBAL void UMF_set_stats +( + double Info [ ], + SymbolicType *Symbolic, + double max_usage, /* peak size of Numeric->Memory, in Units */ + double num_mem_size, /* final size of Numeric->Memory, in Units */ + double flops, /* "true flops" */ + double lnz, /* nz in L */ + double unz, /* nz in U */ + double maxfrsize, /* largest front size */ + double ulen, /* size of Numeric->Upattern */ + double npiv, /* number of pivots found */ + double maxnrows, /* largest #rows in front */ + double maxncols, /* largest #cols in front */ + Int scale, /* true if scaling the rows of A */ + Int prefer_diagonal, /* true if diagonal pivoting (only square A) */ + Int what /* ESTIMATE or ACTUAL */ +) +{ + + double sym_size, work_usage, nn, n_row, n_col, n_inner, num_On_size1, + num_On_size2, num_usage, sym_maxncols, sym_maxnrows, elen, n1 ; + + n_col = Symbolic->n_col ; + n_row = Symbolic->n_row ; + n1 = Symbolic->n1 ; + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + sym_maxncols = MIN (Symbolic->maxncols + Symbolic->nb, n_col) ; + sym_maxnrows = MIN (Symbolic->maxnrows + Symbolic->nb, n_row) ; + elen = (n_col - n1) + (n_row - n1) + MIN (n_col - n1, n_row - n1) + 1 ; + + /* final Symbolic object size */ + sym_size = UMF_symbolic_usage (Symbolic->n_row, Symbolic->n_col, + Symbolic->nchains, Symbolic->nfr, Symbolic->esize, prefer_diagonal) ; + + /* size of O(n) part of Numeric object during factorization, */ + /* except Numeric->Memory and Numeric->Upattern */ + num_On_size1 = + DUNITS (NumericType, 1) /* Numeric structure */ + + DUNITS (Entry, n_inner+1) /* D */ + + 4 * DUNITS (Int, n_row+1) /* Rperm, Lpos, Uilen, Uip */ + + 4 * DUNITS (Int, n_col+1) /* Cperm, Upos, Lilen, Lip */ + + (scale ? DUNITS (Entry, n_row) : 0) ; /* Rs, row scale factors */ + + /* size of O(n) part of Numeric object after factorization, */ + /* except Numeric->Memory and Numeric->Upattern */ + num_On_size2 = + DUNITS (NumericType, 1) /* Numeric structure */ + + DUNITS (Entry, n_inner+1) /* D */ + + DUNITS (Int, n_row+1) /* Rperm */ + + DUNITS (Int, n_col+1) /* Cperm */ + + 6 * DUNITS (Int, npiv+1) /* Lpos, Uilen, Uip, Upos, Lilen, Lip */ + + (scale ? DUNITS (Entry, n_row) : 0) ; /* Rs, row scale factors */ + + DEBUG1 (("num O(n) size2: %g\n", num_On_size2)) ; + + /* peak size of Numeric->Memory, including LU factors, current frontal + * matrix, elements, and tuple lists. */ + Info [UMFPACK_VARIABLE_PEAK + what] = max_usage ; + + /* final size of Numeric->Memory (LU factors only) */ + Info [UMFPACK_VARIABLE_FINAL + what] = num_mem_size ; + + /* final size of Numeric object, including Numeric->Memory and ->Upattern */ + Info [UMFPACK_NUMERIC_SIZE + what] = + num_On_size2 + + num_mem_size /* final Numeric->Memory size */ + + DUNITS (Int, ulen+1) ;/* Numeric->Upattern (from Work->Upattern) */ + + DEBUG1 (("num mem size: %g\n", num_mem_size)) ; + DEBUG1 (("ulen units %g\n", DUNITS (Int, ulen))) ; + DEBUG1 (("numeric size %g\n", Info [UMFPACK_NUMERIC_SIZE + what])) ; + + /* largest front size (working array size, or actual size used) */ + Info [UMFPACK_MAX_FRONT_SIZE + what] = maxfrsize ; + Info [UMFPACK_MAX_FRONT_NROWS + what] = maxnrows ; + Info [UMFPACK_MAX_FRONT_NCOLS + what] = maxncols ; + DEBUGm4 (("maxnrows %g maxncols %g\n", maxnrows, maxncols)) ; + DEBUGm4 (("maxfrsize %g\n", maxfrsize)) ; + + /* UMF_kernel usage, from work_alloc routine in umf_kernel.c */ + work_usage = + /* Work-> arrays, except for current frontal matrix which is allocated + * inside Numeric->Memory. */ + 2 * DUNITS (Entry, sym_maxnrows + 1) /* Wx, Wy */ + + 2 * DUNITS (Int, n_row+1) /* Frpos, Lpattern */ + + 2 * DUNITS (Int, n_col+1) /* Fcpos, Upattern */ + + DUNITS (Int, nn + 1) /* Wp */ + + DUNITS (Int, MAX (n_col, sym_maxnrows) + 1) /* Wrp */ + + 2 * DUNITS (Int, sym_maxnrows + 1) /* Frows, Wm */ + + 3 * DUNITS (Int, sym_maxncols + 1) /* Fcols, Wio, Woi */ + + DUNITS (Int, MAX (sym_maxnrows, sym_maxncols) + 1) /* Woo */ + + DUNITS (Int, elen) /* E */ + + DUNITS (Int, Symbolic->nfr + 1) /* Front_new1strow */ + + ((n_row == n_col) ? (2 * DUNITS (Int, nn)) : 0) ; /* Diag map,imap */ + + /* Peak memory for just UMFPACK_numeric. */ + num_usage = + sym_size /* size of Symbolic object */ + + num_On_size1 /* O(n) part of Numeric object (excl. Upattern) */ + + work_usage /* Work-> arrays (including Upattern) */ + + max_usage ; /* peak size of Numeric->Memory */ + + /* peak memory usage for both UMFPACK_*symbolic and UMFPACK_numeric. */ + Info [UMFPACK_PEAK_MEMORY + what] = + MAX (Symbolic->peak_sym_usage, num_usage) ; + + Info [UMFPACK_FLOPS + what] = flops ; + Info [UMFPACK_LNZ + what] = lnz ; + Info [UMFPACK_UNZ + what] = unz ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.h b/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_set_stats.h @@ -0,0 +1,24 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL void UMF_set_stats +( + double Info [ ], + SymbolicType *Symbolic, + double max_usage, + double num_mem_size, + double flops, + double lnz, + double unz, + double maxfrsize, + double ulen, + double npiv, + double maxnrows, + double maxncols, + Int scale, + Int prefer_diagonal, + Int what +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.c b/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.c @@ -0,0 +1,915 @@ +/* ========================================================================== */ +/* === UMF_singletons ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Find and order the row and column singletons of a matrix A. If there are + * row and column singletons, the output is a row and column permutation such + * that the matrix is in the following form: + * + * x x x x x x x x x + * 0 x x x x x x x x + * 0 0 x x x x x x x + * 0 0 0 x 0 0 0 0 0 + * 0 0 0 x x 0 0 0 0 + * 0 0 0 x x s s s s + * 0 0 0 x x s s s s + * 0 0 0 x x s s s s + * 0 0 0 x x s s s s + * + * The above example has 3 column singletons (the first three columns and + * their corresponding pivot rows) and 2 row singletons. The singletons are + * ordered first, because they have zero Markowitz cost. The LU factorization + * for these first five rows and columns is free - there is no work to do + * (except to scale the pivot columns for the 2 row singletons), and no + * fill-in occurs. * The remaining * submatrix (4-by-4 in the above example) + * has no rows or columns with degree one. It may have empty rows or columns. + * + * This algorithm does not perform a full permutation to block triangular + * form. If there are one or more singletons, then the matrix can be + * permuted to block triangular form, but UMFPACK does not perform the full + * BTF permutation (see also "dmperm" in MATLAB). + */ + +#include "umf_internal.h" + +#ifndef NDEBUG + +/* ========================================================================== */ +/* === debug routines ======================================================= */ +/* ========================================================================== */ + +/* Dump the singleton queue */ + +PRIVATE void dump_singletons +( + Int head, /* head of the queue */ + Int tail, /* tail of the queue */ + Int Next [ ], /* Next [i] is the next object after i */ + char *name, /* "row" or "col" */ + Int Deg [ ], /* Deg [i] is the degree of object i */ + Int n /* objects are in the range 0 to n-1 */ +) +{ + Int i, next, cnt ; + DEBUG6 (("%s Singleton list: head "ID" tail "ID"\n", name, head, tail)) ; + i = head ; + ASSERT (head >= EMPTY && head < n) ; + ASSERT (tail >= EMPTY && tail < n) ; + cnt = 0 ; + while (i != EMPTY) + { + DEBUG7 ((" "ID": "ID" deg: "ID"\n", cnt, i, Deg [i])) ; + ASSERT (i >= 0 && i < n) ; + next = Next [i] ; + if (i == tail) ASSERT (next == EMPTY) ; + i = next ; + cnt++ ; + ASSERT (cnt <= n) ; + } +} + +PRIVATE void dump_mat +( + char *xname, + char *yname, + Int nx, + Int ny, + const Int Xp [ ], + const Int Xi [ ], + Int Xdeg [ ], + Int Ydeg [ ] +) +{ + Int x, y, p, p1, p2, xdeg, do_xdeg, ydeg ; + DEBUG6 (("\n ==== Dump %s mat:\n", xname)) ; + for (x = 0 ; x < nx ; x++) + { + p1 = Xp [x] ; + p2 = Xp [x+1] ; + xdeg = Xdeg [x] ; + DEBUG6 (("Dump %s "ID" p1 "ID" p2 "ID" deg "ID"\n", + xname, x, p1, p2, xdeg)) ; + do_xdeg = (xdeg >= 0) ; + for (p = p1 ; p < p2 ; p++) + { + y = Xi [p] ; + DEBUG7 ((" %s "ID" deg: ", yname, y)) ; + ASSERT (y >= 0 && y < ny) ; + ydeg = Ydeg [y] ; + DEBUG7 ((ID"\n", ydeg)) ; + if (do_xdeg && ydeg >= 0) + { + xdeg-- ; + } + } + ASSERT (IMPLIES (do_xdeg, xdeg == 0)) ; + } +} +#endif + +/* ========================================================================== */ +/* === create_row_form ====================================================== */ +/* ========================================================================== */ + +/* Create the row-form R of the column-form input matrix A. This could be done + * by UMF_transpose, except that Rdeg has already been computed. + */ + +PRIVATE void create_row_form +( + /* input, not modified: */ + Int n_row, /* A is n_row-by-n_col, nz = Ap [n_col] */ + Int n_col, + const Int Ap [ ], /* Ap [0..n_col]: column pointers for A */ + const Int Ai [ ], /* Ai [0..nz-1]: row indices for A */ + Int Rdeg [ ], /* Rdeg [0..n_row-1]: row degrees */ + + /* output, not defined on input: */ + Int Rp [ ], /* Rp [0..n_row]: row pointers for R */ + Int Ri [ ], /* Ri [0..nz-1]: column indices for R */ + + /* workspace, not defined on input or output */ + Int W [ ] /* size n_row */ +) +{ + Int row, col, p, p2 ; + + /* create the row pointers */ + Rp [0] = 0 ; + W [0] = 0 ; + for (row = 0 ; row < n_row ; row++) + { + Rp [row+1] = Rp [row] + Rdeg [row] ; + W [row] = Rp [row] ; + } + + /* create the indices for the row-form */ + for (col = 0 ; col < n_col ; col++) + { + p2 = Ap [col+1] ; + for (p = Ap [col] ; p < p2 ; p++) + { + Ri [W [Ai [p]]++] = col ; + } + } +} + +/* ========================================================================== */ +/* === order_singletons ===================================================== */ +/* ========================================================================== */ + +PRIVATE int order_singletons /* return new number of singletons */ +( + Int k, /* the number of singletons so far */ + Int head, + Int tail, + Int Next [ ], + Int Xdeg [ ], Int Xperm [ ], const Int Xp [ ], const Int Xi [ ], + Int Ydeg [ ], Int Yperm [ ], const Int Yp [ ], const Int Yi [ ] +#ifndef NDEBUG + , char *xname, char *yname, Int nx, Int ny +#endif +) +{ + Int xpivot, x, y, ypivot, p, p2, deg ; + +#ifndef NDEBUG + Int i, k1 = k ; + dump_singletons (head, tail, Next, xname, Xdeg, nx) ; + dump_mat (xname, yname, nx, ny, Xp, Xi, Xdeg, Ydeg) ; + dump_mat (yname, xname, ny, nx, Yp, Yi, Ydeg, Xdeg) ; +#endif + + while (head != EMPTY) + { + /* remove the singleton at the head of the queue */ + xpivot = head ; + DEBUG1 (("------ Order %s singleton: "ID"\n", xname, xpivot)) ; + head = Next [xpivot] ; + if (head == EMPTY) tail = EMPTY ; + +#ifndef NDEBUG + if (k % 100 == 0) dump_singletons (head, tail, Next, xname, Xdeg, nx) ; +#endif + + ASSERT (Xdeg [xpivot] >= 0) ; + if (Xdeg [xpivot] != 1) + { + /* This row/column x is empty. The matrix is singular. + * x will be ordered last in Xperm. */ + DEBUG1 (("empty %s, after singletons removed\n", xname)) ; + continue ; + } + + /* find the ypivot to match with this xpivot */ +#ifndef NDEBUG + /* there can only be one ypivot, since the degree of x is 1 */ + deg = 0 ; + p2 = Xp [xpivot+1] ; + for (p = Xp [xpivot] ; p < p2 ; p++) + { + y = Xi [p] ; + DEBUG1 (("%s: "ID"\n", yname, y)) ; + if (Ydeg [y] >= 0) + { + /* this is a live index in this xpivot vector */ + deg++ ; + } + } + ASSERT (deg == 1) ; +#endif + + ypivot = EMPTY ; + p2 = Xp [xpivot+1] ; + for (p = Xp [xpivot] ; p < p2 ; p++) + { + y = Xi [p] ; + DEBUG1 (("%s: "ID"\n", yname, y)) ; + if (Ydeg [y] >= 0) + { + /* this is a live index in this xpivot vector */ + ypivot = y ; + break ; + } + } + + DEBUG1 (("Pivot %s: "ID"\n", yname, ypivot)) ; + ASSERT (ypivot != EMPTY) ; + DEBUG1 (("deg "ID"\n", Ydeg [ypivot])) ; + ASSERT (Ydeg [ypivot] >= 0) ; + + /* decrement the degrees after removing this singleton */ + DEBUG1 (("p1 "ID"\n", Yp [ypivot])) ; + DEBUG1 (("p2 "ID"\n", Yp [ypivot+1])) ; + p2 = Yp [ypivot+1] ; + for (p = Yp [ypivot] ; p < p2 ; p++) + { + x = Yi [p] ; + DEBUG1 ((" %s: "ID" deg: "ID"\n", xname, x, Xdeg [x])) ; + if (Xdeg [x] < 0) continue ; + ASSERT (Xdeg [x] > 0) ; + if (x == xpivot) continue ; + deg = --(Xdeg [x]) ; + ASSERT (Xdeg [x] >= 0) ; + if (deg == 1) + { + /* this is a new singleton, put at the end of the queue */ + Next [x] = EMPTY ; + if (head == EMPTY) + { + head = x ; + } + else + { + ASSERT (tail != EMPTY) ; + Next [tail] = x ; + } + tail = x ; + DEBUG1 ((" New %s singleton: "ID"\n", xname, x)) ; +#ifndef NDEBUG + if (k % 100 == 0) + { + dump_singletons (head, tail, Next, xname, Xdeg, nx) ; + } +#endif + } + } + + /* flag the xpivot and ypivot by FLIP'ing the degrees */ + Xdeg [xpivot] = FLIP (1) ; + Ydeg [ypivot] = FLIP (Ydeg [ypivot]) ; + + /* keep track of the pivot row and column */ + Xperm [k] = xpivot ; + Yperm [k] = ypivot ; + k++ ; + +#ifndef NDEBUG + if (k % 1000 == 0) + { + dump_mat (xname, yname, nx, ny, Xp, Xi, Xdeg, Ydeg) ; + dump_mat (yname, xname, ny, nx, Yp, Yi, Ydeg, Xdeg) ; + } +#endif + } + +#ifndef NDEBUG + DEBUGm4 (("%s singletons: k = "ID"\n", xname, k)) ; + for (i = k1 ; i < k ; i++) + { + DEBUG1 ((" %s: "ID" %s: "ID"\n", xname, Xperm [i], yname, Yperm [i])) ; + } + ASSERT (k > 0) ; +#endif + + return (k) ; +} + +/* ========================================================================== */ +/* === find_any_singletons ================================================== */ +/* ========================================================================== */ + +PRIVATE Int find_any_singletons /* returns # of singletons found */ +( + /* input, not modified: */ + Int n_row, + Int n_col, + const Int Ap [ ], /* size n_col+1 */ + const Int Ai [ ], /* size nz = Ap [n_col] */ + + /* input, modified on output: */ + Int Cdeg [ ], /* size n_col */ + Int Rdeg [ ], /* size n_row */ + + /* output, not defined on input: */ + Int Cperm [ ], /* size n_col */ + Int Rperm [ ], /* size n_row */ + Int *p_n1r, /* # of row singletons */ + Int *p_n1c, /* # of col singletons */ + + /* workspace, not defined on input or output */ + Int Rp [ ], /* size n_row+1 */ + Int Ri [ ], /* size nz */ + Int W [ ], /* size n_row */ + Int Next [ ] /* size MAX (n_row, n_col) */ +) +{ + Int n1, col, row, row_form, head, tail, n1r, n1c ; + + /* ---------------------------------------------------------------------- */ + /* eliminate column singletons */ + /* ---------------------------------------------------------------------- */ + + n1 = 0 ; + n1r = 0 ; + n1c = 0 ; + row_form = FALSE ; + + head = EMPTY ; + tail = EMPTY ; + for (col = n_col-1 ; col >= 0 ; col--) + { + if (Cdeg [col] == 1) + { + /* put the column singleton in the queue */ + if (head == EMPTY) tail = col ; + Next [col] = head ; + head = col ; + DEBUG1 (("Column singleton: "ID"\n", col)) ; + } + } + + if (head != EMPTY) + { + + /* ------------------------------------------------------------------ */ + /* create the row-form of A */ + /* ------------------------------------------------------------------ */ + + create_row_form (n_row, n_col, Ap, Ai, Rdeg, Rp, Ri, W) ; + row_form = TRUE ; + + /* ------------------------------------------------------------------ */ + /* find and order the column singletons */ + /* ------------------------------------------------------------------ */ + + n1 = order_singletons (0, head, tail, Next, + Cdeg, Cperm, Ap, Ai, + Rdeg, Rperm, Rp, Ri +#ifndef NDEBUG + , "col", "row", n_col, n_row +#endif + ) ; + n1c = n1 ; + } + + /* ---------------------------------------------------------------------- */ + /* eliminate row singletons */ + /* ---------------------------------------------------------------------- */ + + head = EMPTY ; + tail = EMPTY ; + for (row = n_row-1 ; row >= 0 ; row--) + { + if (Rdeg [row] == 1) + { + /* put the row singleton in the queue */ + if (head == EMPTY) tail = row ; + Next [row] = head ; + head = row ; + DEBUG1 (("Row singleton: "ID"\n", row)) ; + } + } + + if (head != EMPTY) + { + + /* ------------------------------------------------------------------ */ + /* create the row-form of A, if not already created */ + /* ------------------------------------------------------------------ */ + + if (!row_form) + { + create_row_form (n_row, n_col, Ap, Ai, Rdeg, Rp, Ri, W) ; + } + + /* ------------------------------------------------------------------ */ + /* find and order the row singletons */ + /* ------------------------------------------------------------------ */ + + n1 = order_singletons (n1, head, tail, Next, + Rdeg, Rperm, Rp, Ri, + Cdeg, Cperm, Ap, Ai +#ifndef NDEBUG + , "row", "col", n_row, n_col +#endif + ) ; + n1r = n1 - n1c ; + } + + DEBUG0 (("n1 "ID"\n", n1)) ; + *p_n1r = n1r ; + *p_n1c = n1c ; + return (n1) ; +} + +/* ========================================================================== */ +/* === find_user_singletons ================================================= */ +/* ========================================================================== */ + +PRIVATE Int find_user_singletons /* returns # singletons found */ +( + /* input, not modified: */ + Int n_row, + Int n_col, + const Int Ap [ ], /* size n_col+1 */ + const Int Ai [ ], /* size nz = Ap [n_col] */ + const Int Quser [ ], /* size n_col if present */ + + /* input, modified on output: */ + Int Cdeg [ ], /* size n_col */ + Int Rdeg [ ], /* size n_row */ + + /* output, not defined on input */ + Int Cperm [ ], /* size n_col */ + Int Rperm [ ], /* size n_row */ + Int *p_n1r, /* # of row singletons */ + Int *p_n1c, /* # of col singletons */ + + /* workspace, not defined on input or output */ + Int Rp [ ], /* size n_row+1 */ + Int Ri [ ], /* size nz */ + Int W [ ] /* size n_row */ +) +{ + Int n1, col, row, p, p2, pivcol, pivrow, found, k, n1r, n1c ; + + n1 = 0 ; + n1r = 0 ; + n1c = 0 ; + *p_n1r = 0 ; + *p_n1c = 0 ; + + /* find singletons in the user column permutation, Quser */ + pivcol = Quser [0] ; + found = (Cdeg [pivcol] == 1) ; + DEBUG0 (("Is first col: "ID" a col singleton?: "ID"\n", pivcol, found)) ; + if (!found) + { + /* the first column is not a column singleton, check for a row + * singleton in the first column. */ + for (p = Ap [pivcol] ; p < Ap [pivcol+1] ; p++) + { + if (Rdeg [Ai [p]] == 1) + { + DEBUG0 (("Row singleton in first col: "ID" row: "ID"\n", + pivcol, Ai [p])) ; + found = TRUE ; + break ; + } + } + } + + if (!found) + { + /* no singletons in the leading part of A (:,Quser) */ + return (0) ; + } + + /* there is at least one row or column singleton. Look for more. */ + create_row_form (n_row, n_col, Ap, Ai, Rdeg, Rp, Ri, W) ; + + n1 = 0 ; + + for (k = 0 ; k < n_col ; k++) + { + pivcol = Quser [k] ; + pivrow = EMPTY ; + + /* ------------------------------------------------------------------ */ + /* check if col is a column singleton, or contains a row singleton */ + /* ------------------------------------------------------------------ */ + + found = (Cdeg [pivcol] == 1) ; + + if (found) + { + + /* -------------------------------------------------------------- */ + /* pivcol is a column singleton */ + /* -------------------------------------------------------------- */ + + DEBUG0 (("Found a col singleton: k "ID" pivcol "ID"\n", k, pivcol)); + + /* find the pivrow to match with this pivcol */ +#ifndef NDEBUG + /* there can only be one pivrow, since the degree of pivcol is 1 */ + { + Int deg = 0 ; + p2 = Ap [pivcol+1] ; + for (p = Ap [pivcol] ; p < p2 ; p++) + { + row = Ai [p] ; + DEBUG1 (("row: "ID"\n", row)) ; + if (Rdeg [row] >= 0) + { + /* this is a live index in this column vector */ + deg++ ; + } + } + ASSERT (deg == 1) ; + } +#endif + + p2 = Ap [pivcol+1] ; + for (p = Ap [pivcol] ; p < p2 ; p++) + { + row = Ai [p] ; + DEBUG1 (("row: "ID"\n", row)) ; + if (Rdeg [row] >= 0) + { + /* this is a live index in this pivcol vector */ + pivrow = row ; + break ; + } + } + + DEBUG1 (("Pivot row: "ID"\n", pivrow)) ; + ASSERT (pivrow != EMPTY) ; + DEBUG1 (("deg "ID"\n", Rdeg [pivrow])) ; + ASSERT (Rdeg [pivrow] >= 0) ; + + /* decrement the degrees after removing this col singleton */ + DEBUG1 (("p1 "ID"\n", Rp [pivrow])) ; + DEBUG1 (("p2 "ID"\n", Rp [pivrow+1])) ; + p2 = Rp [pivrow+1] ; + for (p = Rp [pivrow] ; p < p2 ; p++) + { + col = Ri [p] ; + DEBUG1 ((" col: "ID" deg: "ID"\n", col, Cdeg [col])) ; + if (Cdeg [col] < 0) continue ; + ASSERT (Cdeg [col] > 0) ; + Cdeg [col]-- ; + ASSERT (Cdeg [col] >= 0) ; + } + + /* flag the pivcol and pivrow by FLIP'ing the degrees */ + Cdeg [pivcol] = FLIP (1) ; + Rdeg [pivrow] = FLIP (Rdeg [pivrow]) ; + n1c++ ; + + } + else + { + + /* -------------------------------------------------------------- */ + /* pivcol may contain a row singleton */ + /* -------------------------------------------------------------- */ + + p2 = Ap [pivcol+1] ; + for (p = Ap [pivcol] ; p < p2 ; p++) + { + pivrow = Ai [p] ; + if (Rdeg [pivrow] == 1) + { + DEBUG0 (("Row singleton in pivcol: "ID" row: "ID"\n", + pivcol, pivrow)) ; + found = TRUE ; + break ; + } + } + + if (!found) + { + DEBUG0 (("End of user singletons\n")) ; + break ; + } + +#ifndef NDEBUG + /* there can only be one pivrow, since the degree of pivcol is 1 */ + { + Int deg = 0 ; + p2 = Rp [pivrow+1] ; + for (p = Rp [pivrow] ; p < p2 ; p++) + { + col = Ri [p] ; + DEBUG1 (("col: "ID" cdeg::: "ID"\n", col, Cdeg [col])) ; + if (Cdeg [col] >= 0) + { + /* this is a live index in this column vector */ + ASSERT (col == pivcol) ; + deg++ ; + } + } + ASSERT (deg == 1) ; + } +#endif + + DEBUG1 (("Pivot row: "ID"\n", pivrow)) ; + DEBUG1 (("pivcol deg "ID"\n", Cdeg [pivcol])) ; + ASSERT (Cdeg [pivcol] > 1) ; + + /* decrement the degrees after removing this row singleton */ + DEBUG1 (("p1 "ID"\n", Ap [pivcol])) ; + DEBUG1 (("p2 "ID"\n", Ap [pivcol+1])) ; + p2 = Ap [pivcol+1] ; + for (p = Ap [pivcol] ; p < p2 ; p++) + { + row = Ai [p] ; + DEBUG1 ((" row: "ID" deg: "ID"\n", row, Rdeg [row])) ; + if (Rdeg [row] < 0) continue ; + ASSERT (Rdeg [row] > 0) ; + Rdeg [row]-- ; + ASSERT (Rdeg [row] >= 0) ; + } + + /* flag the pivcol and pivrow by FLIP'ing the degrees */ + Cdeg [pivcol] = FLIP (Cdeg [pivcol]) ; + Rdeg [pivrow] = FLIP (1) ; + n1r++ ; + } + + /* keep track of the pivot row and column */ + Cperm [k] = pivcol ; + Rperm [k] = pivrow ; + n1++ ; + +#ifndef NDEBUG + dump_mat ("col", "row", n_col, n_row, Ap, Ai, Cdeg, Rdeg) ; + dump_mat ("row", "col", n_row, n_col, Rp, Ri, Rdeg, Cdeg) ; +#endif + + } + + DEBUGm4 (("User singletons found: "ID"\n", n1)) ; + ASSERT (n1 > 0) ; + + *p_n1r = n1r ; + *p_n1c = n1c ; + return (n1) ; +} + +/* ========================================================================== */ +/* === finish_permutation =================================================== */ +/* ========================================================================== */ + +/* Complete the permutation for the pruned submatrix. The singletons are + * already ordered, but remove their flags. Place rows/columns that are empty + * in the pruned submatrix at the end of the output permutation. This can only + * occur if the matrix is singular. + */ + +PRIVATE Int finish_permutation +( + Int n1, + Int nx, + Int Xdeg [ ], + const Int Xuser [ ], + Int Xperm [ ], + Int *p_max_deg +) +{ + Int nempty, x, deg, s, max_deg, k ; + nempty = 0 ; + s = n1 ; + max_deg = 0 ; + DEBUG0 (("n1 "ID" nempty "ID"\n", n1, nempty)) ; + for (k = 0 ; k < nx ; k++) + { + x = (Xuser != (Int *) NULL) ? Xuser [k] : k ; + DEBUG0 (("finish perm k "ID" x "ID" nx "ID"\n", k, x, nx)) ; + deg = Xdeg [x] ; + if (deg == 0) + { + /* this row/col is empty in the pruned submatrix */ + ASSERT (s < nx - nempty) ; + DEBUG0 (("empty k "ID"\n", k)) ; + nempty++ ; + Xperm [nx - nempty] = x ; + } + else if (deg > 0) + { + /* this row/col is nonempty in the pruned submatrix */ + ASSERT (s < nx - nempty) ; + Xperm [s++] = x ; + max_deg = MAX (max_deg, deg) ; + } + else + { + /* This is a singleton row/column - it is already ordered. + * Just clear the flag. */ + Xdeg [x] = FLIP (deg) ; + } + } + ASSERT (s == nx - nempty) ; + *p_max_deg = max_deg ; + return (nempty) ; +} + +/* ========================================================================== */ +/* === UMF_singletons ======================================================= */ +/* ========================================================================== */ + +GLOBAL Int UMF_singletons +( + + /* input, not modified: */ + Int n_row, + Int n_col, + const Int Ap [ ], /* size n_col+1 */ + const Int Ai [ ], /* size nz = Ap [n_col] */ + const Int Quser [ ], /* size n_col if present */ + Int strategy, /* strategy requested by user */ + + /* output, not defined on input: */ + Int Cdeg [ ], /* size n_col */ + Int Cperm [ ], /* size n_col */ + Int Rdeg [ ], /* size n_row */ + Int Rperm [ ], /* size n_row */ + Int InvRperm [ ], /* size n_row, the inverse of Rperm */ + Int *p_n1, /* # of col and row singletons */ + Int *p_n1c, /* # of col singletons */ + Int *p_n1r, /* # of row singletons */ + Int *p_nempty_col, /* # of empty columns in pruned submatrix */ + Int *p_nempty_row, /* # of empty columns in pruned submatrix */ + Int *p_is_sym, /* TRUE if pruned submatrix is square and has been + * symmetrically permuted by Cperm and Rperm */ + Int *p_max_rdeg, /* maximum Rdeg in pruned submatrix */ + + /* workspace, not defined on input or output */ + Int Rp [ ], /* size n_row+1 */ + Int Ri [ ], /* size nz */ + Int W [ ], /* size n_row */ + Int Next [ ] /* size MAX (n_row, n_col) */ +) +{ + Int n1, s, col, row, p, p1, p2, cdeg, last_row, is_sym, k, + nempty_row, nempty_col, max_cdeg, max_rdeg, n1c, n1r ; + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_dump_start ( ) ; + DEBUGm4 (("Starting umf_singletons\n")) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* scan the columns, check for errors and count row degrees */ + /* ---------------------------------------------------------------------- */ + + if (Ap [0] != 0 || Ap [n_col] < 0) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + for (row = 0 ; row < n_row ; row++) + { + Rdeg [row] = 0 ; + } + for (col = 0 ; col < n_col ; col++) + { + p1 = Ap [col] ; + p2 = Ap [col+1] ; + cdeg = p2 - p1 ; + if (cdeg < 0) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + last_row = EMPTY ; + for (p = p1 ; p < p2 ; p++) + { + row = Ai [p] ; + if (row <= last_row || row >= n_row) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + Rdeg [row]++ ; + last_row = row ; + } + Cdeg [col] = cdeg ; + } + + /* ---------------------------------------------------------------------- */ + /* find singletons */ + /* ---------------------------------------------------------------------- */ + + if (Quser != (Int *) NULL) + { + /* user has provided an input column ordering */ + if (strategy == UMFPACK_STRATEGY_UNSYMMETRIC) + { + /* look for singletons, but respect the user's input permutation */ + n1 = find_user_singletons (n_row, n_col, Ap, Ai, Quser, + Cdeg, Rdeg, Cperm, Rperm, &n1r, &n1c, Rp, Ri, W) ; + } + else + { + /* do not look for singletons if Quser given and strategy is + * not unsymmetric */ + n1 = 0 ; + n1r = 0 ; + n1c = 0 ; + } + } + else + { + /* look for singletons anywhere */ + n1 = find_any_singletons (n_row, n_col, Ap, Ai, + Cdeg, Rdeg, Cperm, Rperm, &n1r, &n1c, Rp, Ri, W, Next) ; + } + + /* ---------------------------------------------------------------------- */ + /* eliminate empty columns and complete the column permutation */ + /* ---------------------------------------------------------------------- */ + + nempty_col = finish_permutation (n1, n_col, Cdeg, Quser, Cperm, &max_cdeg) ; + + /* ---------------------------------------------------------------------- */ + /* eliminate empty rows and complete the row permutation */ + /* ---------------------------------------------------------------------- */ + + if (Quser != (Int *) NULL && strategy == UMFPACK_STRATEGY_SYMMETRIC) + { + /* rows should be symmetrically permuted according to Quser */ + ASSERT (n_row == n_col) ; + nempty_row = finish_permutation (n1, n_row, Rdeg, Quser, Rperm, + &max_rdeg) ; + } + else + { + /* rows should not be symmetrically permuted according to Quser */ + nempty_row = finish_permutation (n1, n_row, Rdeg, (Int *) NULL, Rperm, + &max_rdeg) ; + } + + /* ---------------------------------------------------------------------- */ + /* compute the inverse of Rperm */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n_row ; k++) + { + ASSERT (Rperm [k] >= 0 && Rperm [k] < n_row) ; + InvRperm [Rperm [k]] = k ; + } + + /* ---------------------------------------------------------------------- */ + /* see if pruned submatrix is square and has been symmetrically permuted */ + /* ---------------------------------------------------------------------- */ + + if (n_row == n_col && nempty_row == nempty_col) + { + /* is_sym is true if the submatrix is square, and + * Rperm [n1..n_row-nempty_row-1] = Cperm [n1..n_col-nempty_col-1] */ + is_sym = TRUE ; + for (s = n1 ; s < n_col - nempty_col ; s++) + { + if (Cperm [s] != Rperm [s]) + { + is_sym = FALSE ; + break ; + } + } + } + else + { + is_sym = FALSE ; + } + DEBUGm4 (("Submatrix square and symmetrically permuted? "ID"\n", is_sym)) ; + DEBUGm4 (("singletons "ID" row "ID" col "ID"\n", n1, n1r, n1c)) ; + DEBUGm4 (("Empty cols "ID" rows "ID"\n", nempty_col, nempty_row)) ; + *p_n1 = n1 ; + *p_n1r = n1r ; + *p_n1c = n1c ; + *p_is_sym = is_sym ; + *p_nempty_col = nempty_col ; + *p_nempty_row = nempty_row ; + *p_max_rdeg = max_rdeg ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.h b/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_singletons.h @@ -0,0 +1,31 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_singletons +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const Int Quser [ ], + Int strategy, + Int Cdeg [ ], + Int Cperm [ ], + Int Rdeg [ ], + Int Rperm [ ], + Int InvRperm [ ], + Int *n1, + Int *n1c, + Int *n1r, + Int *nempty_col, + Int *nempty_row, + Int *is_sym, + Int *max_rdeg, + Int Rp [ ], + Int Ri [ ], + Int W [ ], + Int Next [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_solve.c b/liboctave/UMFPACK/UMFPACK/Source/umf_solve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_solve.c @@ -0,0 +1,1392 @@ +/* ========================================================================== */ +/* === UMF_solve ============================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Not user-callable. Solves a linear system using the numerical factorization + computed by UMFPACK_numeric. No workspace is dynamically allocated. Counts + flops, but excludes floating-point comparisons (thus real abs (...) are + zero flops, but complex abs (...) takes 6 flops). + + Returns UMFPACK_OK if successful, UMFPACK_ERROR_argument_missing if + required arguments are missing, UMFPACK_ERROR_invalid_system if the sys + string is not valid or if the matrix A is not square. + + Uses the sparse backward error method of Arioli, Demmel, and Duff + (Solving sparse linear systems with sparse backward error, SIAM J. Matrix + Analysis and Applic., vol 10, pp. 165-190). +*/ + +#include "umf_internal.h" +#include "umf_lsolve.h" +#include "umf_usolve.h" +#include "umf_ltsolve.h" +#include "umf_utsolve.h" +#include "umf_report_vector.h" + +PRIVATE Int do_step +( + double omega [3], + Int step, + const double B2 [ ], + Entry X [ ], + const Entry W [ ], + const double Y [ ], + const double Z2 [ ], + Entry S [ ], + Int n, + double Info [UMFPACK_INFO] +) ; + +/* ========================================================================== */ +/* === UMF_solve ============================================================ */ +/* ========================================================================== */ + +GLOBAL Int UMF_solve +( + Int sys, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], + double Xx [ ], + const double Bx [ ], +#ifdef COMPLEX + const double Az [ ], + double Xz [ ], + const double Bz [ ], +#endif + NumericType *Numeric, + Int irstep, + double Info [UMFPACK_INFO], + Int Pattern [ ], /* size n */ + double SolveWork [ ] /* if irstep>0 real: size 5*n. complex:10*n */ + /* otherwise real: size n. complex: 4*n */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry axx, wi, xj, zi, xi, aij, bi ; + double omega [3], d, z2i, yi, flops ; + Entry *W, *Z, *S, *X ; + double *Z2, *Y, *B2, *Rs ; + Int *Rperm, *Cperm, i, n, p, step, j, nz, status, p2, do_scale ; +#ifdef COMPLEX + Int AXsplit ; + Int Bsplit ; +#endif +#ifndef NRECIPROCAL + Int do_recip = Numeric->do_recip ; +#endif + + /* ---------------------------------------------------------------------- */ + /* initializations */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_dump_lu (Numeric) ; + ASSERT (Numeric && Xx && Bx && Pattern && SolveWork && Info) ; +#endif + + nz = 0 ; + omega [0] = 0. ; + omega [1] = 0. ; + omega [2] = 0. ; + Rperm = Numeric->Rperm ; + Cperm = Numeric->Cperm ; + Rs = Numeric->Rs ; /* row scale factors */ + do_scale = (Rs != (double *) NULL) ; + flops = 0 ; + Info [UMFPACK_SOLVE_FLOPS] = 0 ; + Info [UMFPACK_IR_TAKEN] = 0 ; + Info [UMFPACK_IR_ATTEMPTED] = 0 ; + + /* UMFPACK_solve does not call this routine if A is rectangular */ + ASSERT (Numeric->n_row == Numeric->n_col) ; + n = Numeric->n_row ; + if (Numeric->nnzpiv < n + || SCALAR_IS_ZERO (Numeric->rcond) || SCALAR_IS_NAN (Numeric->rcond)) + { + /* Note that systems involving just L return UMFPACK_OK, even if */ + /* A is singular (L is always has a unit diagonal). */ + DEBUGm4 (("Note, matrix is singular in umf_solve\n")) ; + status = UMFPACK_WARNING_singular_matrix ; + irstep = 0 ; + } + else + { + status = UMFPACK_OK ; + } + irstep = MAX (0, irstep) ; /* make sure irstep is >= 0 */ + + W = (Entry *) SolveWork ; /* Entry W [0..n-1] */ + + Z = (Entry *) NULL ; /* unused if no iterative refinement */ + S = (Entry *) NULL ; + Y = (double *) NULL ; + Z2 = (double *) NULL ; + B2 = (double *) NULL ; + +#ifdef COMPLEX + if (irstep > 0) + { + if (!Ap || !Ai || !Ax) + { + return (UMFPACK_ERROR_argument_missing) ; + } + /* A, B, and X in split format if Az, Bz, and Xz present */ + AXsplit = SPLIT (Az) || SPLIT(Xz); + Z = (Entry *) (SolveWork + 4*n) ; /* Entry Z [0..n-1] */ + S = (Entry *) (SolveWork + 6*n) ; /* Entry S [0..n-1] */ + Y = (double *) (SolveWork + 8*n) ; /* double Y [0..n-1] */ + B2 = (double *) (SolveWork + 9*n) ; /* double B2 [0..n-1] */ + Z2 = (double *) Z ; /* double Z2 [0..n-1], equiv. to Z */ + } + else + { + /* A is ignored, only look at X for split/packed cases */ + AXsplit = SPLIT(Xz); + } + Bsplit = SPLIT (Bz); + + if (AXsplit) + { + X = (Entry *) (SolveWork + 2*n) ; /* Entry X [0..n-1] */ + } + else + { + X = (Entry *) Xx ; /* Entry X [0..n-1] */ + } +#else + X = (Entry *) Xx ; /* Entry X [0..n-1] */ + if (irstep > 0) + { + if (!Ap || !Ai || !Ax) + { + return (UMFPACK_ERROR_argument_missing) ; + } + Z = (Entry *) (SolveWork + n) ; /* Entry Z [0..n-1] */ + S = (Entry *) (SolveWork + 2*n) ; /* Entry S [0..n-1] */ + Y = (double *) (SolveWork + 3*n) ; /* double Y [0..n-1] */ + B2 = (double *) (SolveWork + 4*n) ; /* double B2 [0..n-1] */ + Z2 = (double *) Z ; /* double Z2 [0..n-1], equiv. to Z */ + } +#endif + + /* ---------------------------------------------------------------------- */ + /* determine which system to solve */ + /* ---------------------------------------------------------------------- */ + + if (sys == UMFPACK_A) + { + + /* ------------------------------------------------------------------ */ + /* solve A x = b with optional iterative refinement */ + /* ------------------------------------------------------------------ */ + + if (irstep > 0) + { + + /* -------------------------------------------------------------- */ + /* using iterative refinement: compute Y and B2 */ + /* -------------------------------------------------------------- */ + + nz = Ap [n] ; + Info [UMFPACK_NZ] = nz ; + + /* A is stored by column */ + /* Y (i) = ||R A_i||, 1-norm of row i of R A */ + for (i = 0 ; i < n ; i++) + { + Y [i] = 0. ; + } + flops += (ABS_FLOPS + 1) * nz ; + p2 = Ap [n] ; + for (p = 0 ; p < p2 ; p++) + { + /* Y [Ai [p]] += ABS (Ax [p]) ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + Y [Ai [p]] += d ; + } + + /* B2 = abs (B) */ + flops += ABS_FLOPS * n ; + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ + ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + + /* scale Y and B2. */ + if (do_scale) + { + /* Y = R Y */ + /* B2 = R B2 */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + Y [i] *= Rs [i] ; + B2 [i] *= Rs [i] ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + Y [i] /= Rs [i] ; + B2 [i] /= Rs [i] ; + } + } + + flops += 2 * n ; + } + + } + + for (step = 0 ; step <= irstep ; step++) + { + + /* -------------------------------------------------------------- */ + /* Solve A x = b (step 0): */ + /* x = Q (U \ (L \ (P R b))) */ + /* and then perform iterative refinement (step > 0): */ + /* x = x + Q (U \ (L \ (P R (b - A x)))) */ + /* -------------------------------------------------------------- */ + + if (step == 0) + { + if (do_scale) + { + /* W = P R b, using X as workspace, since Z is not + * allocated if irstep = 0. */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + SCALE (X [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + SCALE_DIV (X [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + for (i = 0 ; i < n ; i++) + { + W [i] = X [Rperm [i]] ; + } + } + else + { + /* W = P b, since the row scaling R = I */ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Rperm [i]] ; */ + ASSIGN (W [i], Bx, Bz, Rperm [i], Bsplit) ; + } + } + } + else + { + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ + ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) + { + xi = X [i] ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* Z [Ai [p]] -= Ax [p] * xi ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_SUB (Z [Ai [p]], aij, xi) ; + } + } + /* scale, Z = R Z */ + if (do_scale) + { +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (Z [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (Z [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + } + for (i = 0 ; i < n ; i++) + { + W [i] = Z [Rperm [i]] ; + } + } + + flops += UMF_lsolve (Numeric, W, Pattern) ; + flops += UMF_usolve (Numeric, W, Pattern) ; + + if (step == 0) + { + for (i = 0 ; i < n ; i++) + { + X [Cperm [i]] = W [i] ; + } + } + else + { + flops += ASSEMBLE_FLOPS * n ; + for (i = 0 ; i < n ; i++) + { + /* X [Cperm [i]] += W [i] ; */ + ASSEMBLE (X [Cperm [i]], W [i]) ; + } + } + + /* -------------------------------------------------------------- */ + /* sparse backward error estimate */ + /* -------------------------------------------------------------- */ + + if (irstep > 0) + { + + /* ---------------------------------------------------------- */ + /* A is stored by column */ + /* W (i) = R (b - A x)_i, residual */ + /* Z2 (i) = R (|A||x|)_i */ + /* ---------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ + ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + Z2 [i] = 0. ; + } + flops += (MULT_FLOPS + DECREMENT_FLOPS + ABS_FLOPS + 1) * nz ; + for (j = 0 ; j < n ; j++) + { + xj = X [j] ; + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + + /* axx = Ax [p] * xj ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT (axx, aij, xj) ; + + /* W [i] -= axx ; */ + DECREMENT (W [i], axx) ; + + /* Z2 [i] += ABS (axx) ; */ + ABS (d, axx) ; + Z2 [i] += d ; + } + } + + /* scale W and Z2 */ + if (do_scale) + { + /* Z2 = R Z2 */ + /* W = R W */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (W [i], Rs [i]) ; + Z2 [i] *= Rs [i] ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (W [i], Rs [i]) ; + Z2 [i] /= Rs [i] ; + } + } + flops += (SCALE_FLOPS + 1) * n ; + } + + flops += (2*ABS_FLOPS + 5) * n ; + if (do_step (omega, step, B2, X, W, Y, Z2, S, n, Info)) + { + /* iterative refinement is done */ + break ; + } + + } + + } + + } + else if (sys == UMFPACK_At) + { + + /* ------------------------------------------------------------------ */ + /* solve A' x = b with optional iterative refinement */ + /* ------------------------------------------------------------------ */ + + /* A' is the complex conjugate transpose */ + + if (irstep > 0) + { + + /* -------------------------------------------------------------- */ + /* using iterative refinement: compute Y */ + /* -------------------------------------------------------------- */ + + nz = Ap [n] ; + Info [UMFPACK_NZ] = nz ; + + /* A' is stored by row */ + /* Y (i) = ||(A' R)_i||, 1-norm of row i of A' R */ + + if (do_scale) + { + flops += (ABS_FLOPS + 2) * nz ; +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) * Rs [Ai [p]] ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d * Rs [Ai [p]]) ; + } + Y [i] = yi ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) / Rs [Ai [p]] ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d / Rs [Ai [p]]) ; + } + Y [i] = yi ; + } + } + } + else + { + /* no scaling */ + flops += (ABS_FLOPS + 1) * nz ; + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) ; */ + /* note that abs (aij) is the same as + * abs (conj (aij)) */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += d ; + } + Y [i] = yi ; + } + } + + /* B2 = abs (B) */ + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ + ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + + } + + for (step = 0 ; step <= irstep ; step++) + { + + /* -------------------------------------------------------------- */ + /* Solve A' x = b (step 0): */ + /* x = R P' (L' \ (U' \ (Q' b))) */ + /* and then perform iterative refinement (step > 0): */ + /* x = x + R P' (L' \ (U' \ (Q' (b - A' x)))) */ + /* -------------------------------------------------------------- */ + + if (step == 0) + { + /* W = Q' b */ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Cperm [i]] ; */ + ASSIGN (W [i], Bx, Bz, Cperm [i], Bsplit) ; + } + } + else + { + /* Z = b - A' x */ + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ + ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) + { + zi = Z [i] ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* zi -= conjugate (Ax [p]) * X [Ai [p]] ; */ + ASSIGN (aij, Ax, Az, p, Bsplit) ; + MULT_SUB_CONJ (zi, X [Ai [p]], aij) ; + } + Z [i] = zi ; + } + /* W = Q' Z */ + for (i = 0 ; i < n ; i++) + { + W [i] = Z [Cperm [i]] ; + } + } + + flops += UMF_uhsolve (Numeric, W, Pattern) ; + flops += UMF_lhsolve (Numeric, W, Pattern) ; + + if (step == 0) + { + + /* X = R P' W */ + /* do not use Z, since it isn't allocated if irstep = 0 */ + + /* X = P' W */ + for (i = 0 ; i < n ; i++) + { + X [Rperm [i]] = W [i] ; + } + if (do_scale) + { + /* X = R X */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (X [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (X [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + } + + } + else + { + + /* Z = P' W */ + for (i = 0 ; i < n ; i++) + { + Z [Rperm [i]] = W [i] ; + } + if (do_scale) + { + /* Z = R Z */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (Z [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (Z [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + } + + flops += ASSEMBLE_FLOPS * n ; + /* X += Z */ + for (i = 0 ; i < n ; i++) + { + /* X [i] += Z [i] ; was +=W[i] in v4.3, which is wrong */ + ASSEMBLE (X [i], Z [i]) ; /* bug fix, v4.3.1 */ + } + } + + /* -------------------------------------------------------------- */ + /* sparse backward error estimate */ + /* -------------------------------------------------------------- */ + + if (irstep > 0) + { + + /* ---------------------------------------------------------- */ + /* A' is stored by row */ + /* W (i) = (b - A' x)_i, residual */ + /* Z2 (i) = (|A'||x|)_i */ + /* ---------------------------------------------------------- */ + + flops += (MULT_FLOPS + DECREMENT_FLOPS + ABS_FLOPS + 1) * nz ; + for (i = 0 ; i < n ; i++) + { + /* wi = B [i] ; */ + ASSIGN (wi, Bx, Bz, i, Bsplit) ; + z2i = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* axx = conjugate (Ax [p]) * X [Ai [p]] ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_CONJ (axx, X [Ai [p]], aij) ; + + /* wi -= axx ; */ + DECREMENT (wi, axx) ; + + /* z2i += ABS (axx) ; */ + ABS (d, axx) ; + z2i += d ; + } + W [i] = wi ; + Z2 [i] = z2i ; + } + + flops += (2*ABS_FLOPS + 5) * n ; + if (do_step (omega, step, B2, X, W, Y, Z2, S, n, Info)) + { + /* iterative refinement is done */ + break ; + } + + } + + } + + } + else if (sys == UMFPACK_Aat) + { + + /* ------------------------------------------------------------------ */ + /* solve A.' x = b with optional iterative refinement */ + /* ------------------------------------------------------------------ */ + + /* A' is the array transpose */ + + if (irstep > 0) + { + + /* -------------------------------------------------------------- */ + /* using iterative refinement: compute Y */ + /* -------------------------------------------------------------- */ + + nz = Ap [n] ; + Info [UMFPACK_NZ] = nz ; + + /* A.' is stored by row */ + /* Y (i) = ||(A.' R)_i||, 1-norm of row i of A.' R */ + + if (do_scale) + { + flops += (ABS_FLOPS + 2) * nz ; +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) * Rs [Ai [p]] ; */ + /* note that A.' is the array transpose, + * so no conjugate */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d * Rs [Ai [p]]) ; + } + Y [i] = yi ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) / Rs [Ai [p]] ; */ + /* note that A.' is the array transpose, + * so no conjugate */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += (d / Rs [Ai [p]]) ; + } + Y [i] = yi ; + } + } + } + else + { + /* no scaling */ + flops += (ABS_FLOPS + 1) * nz ; + for (i = 0 ; i < n ; i++) + { + yi = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* yi += ABS (Ax [p]) */ + /* note that A.' is the array transpose, + * so no conjugate */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + ABS (d, aij) ; + yi += d ; + } + Y [i] = yi ; + } + } + + /* B2 = abs (B) */ + for (i = 0 ; i < n ; i++) + { + /* B2 [i] = ABS (B [i]) ; */ + ASSIGN (bi, Bx, Bz, i, Bsplit) ; + ABS (B2 [i], bi) ; + } + + } + + for (step = 0 ; step <= irstep ; step++) + { + + /* -------------------------------------------------------------- */ + /* Solve A.' x = b (step 0): */ + /* x = R P' (L.' \ (U.' \ (Q' b))) */ + /* and then perform iterative refinement (step > 0): */ + /* x = x + R P' (L.' \ (U.' \ (Q' (b - A.' x)))) */ + /* -------------------------------------------------------------- */ + + if (step == 0) + { + /* W = Q' b */ + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [Cperm [i]] ; */ + ASSIGN (W [i], Bx, Bz, Cperm [i], Bsplit) ; + } + } + else + { + /* Z = b - A.' x */ + for (i = 0 ; i < n ; i++) + { + /* Z [i] = B [i] ; */ + ASSIGN (Z [i], Bx, Bz, i, Bsplit) ; + } + flops += MULTSUB_FLOPS * nz ; + for (i = 0 ; i < n ; i++) + { + zi = Z [i] ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* zi -= Ax [p] * X [Ai [p]] ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT_SUB (zi, aij, X [Ai [p]]) ; + } + Z [i] = zi ; + } + /* W = Q' Z */ + for (i = 0 ; i < n ; i++) + { + W [i] = Z [Cperm [i]] ; + } + } + + flops += UMF_utsolve (Numeric, W, Pattern) ; + flops += UMF_ltsolve (Numeric, W, Pattern) ; + + if (step == 0) + { + + /* X = R P' W */ + /* do not use Z, since it isn't allocated if irstep = 0 */ + + /* X = P' W */ + for (i = 0 ; i < n ; i++) + { + X [Rperm [i]] = W [i] ; + } + if (do_scale) + { + /* X = R X */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (X [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (X [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + } + + } + else + { + + /* Z = P' W */ + for (i = 0 ; i < n ; i++) + { + Z [Rperm [i]] = W [i] ; + } + if (do_scale) + { + /* Z = R Z */ +#ifndef NRECIPROCAL + if (do_recip) + { + /* multiply by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE (Z [i], Rs [i]) ; + } + } + else +#endif + { + /* divide by the scale factors */ + for (i = 0 ; i < n ; i++) + { + SCALE_DIV (Z [i], Rs [i]) ; + } + } + flops += SCALE_FLOPS * n ; + } + + flops += ASSEMBLE_FLOPS * n ; + /* X += Z */ + for (i = 0 ; i < n ; i++) + { + /* X [i] += Z [i] ; was +=W[i] in v4.3, which is wrong */ + ASSEMBLE (X [i], Z [i]) ; /* bug fix, v4.3.1 */ + } + } + + /* -------------------------------------------------------------- */ + /* sparse backward error estimate */ + /* -------------------------------------------------------------- */ + + if (irstep > 0) + { + + /* ---------------------------------------------------------- */ + /* A.' is stored by row */ + /* W (i) = (b - A.' x)_i, residual */ + /* Z (i) = (|A.'||x|)_i */ + /* ---------------------------------------------------------- */ + + flops += (MULT_FLOPS + DECREMENT_FLOPS + ABS_FLOPS + 1) * nz ; + for (i = 0 ; i < n ; i++) + { + /* wi = B [i] ; */ + ASSIGN (wi, Bx, Bz, i, Bsplit) ; + z2i = 0. ; + p2 = Ap [i+1] ; + for (p = Ap [i] ; p < p2 ; p++) + { + /* axx = Ax [p] * X [Ai [p]] ; */ + ASSIGN (aij, Ax, Az, p, AXsplit) ; + MULT (axx, aij, X [Ai [p]]) ; + + /* wi -= axx ; */ + DECREMENT (wi, axx) ; + + /* z2i += ABS (axx) ; */ + ABS (d, axx) ; + z2i += d ; + } + W [i] = wi ; + Z2 [i] = z2i ; + } + + flops += (2*ABS_FLOPS + 5) * n ; + if (do_step (omega, step, B2, X, W, Y, Z2, S, n, Info)) + { + /* iterative refinement is done */ + break ; + } + + } + + } + + } + else if (sys == UMFPACK_Pt_L) + { + + /* ------------------------------------------------------------------ */ + /* Solve P'Lx=b: x = L \ Pb */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Rperm [i]] ; */ + ASSIGN (X [i], Bx, Bz, Rperm [i], Bsplit) ; + } + flops = UMF_lsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_L) + { + + /* ------------------------------------------------------------------ */ + /* Solve Lx=b: x = L \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_Lt_P) + { + + /* ------------------------------------------------------------------ */ + /* Solve L'Px=b: x = P' (L' \ b) */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ + ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lhsolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) + { + X [Rperm [i]] = W [i] ; + } + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_Lat_P) + { + + /* ------------------------------------------------------------------ */ + /* Solve L.'Px=b: x = P' (L.' \ b) */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ + ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_ltsolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) + { + X [Rperm [i]] = W [i] ; + } + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_Lt) + { + + /* ------------------------------------------------------------------ */ + /* Solve L'x=b: x = L' \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_lhsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_Lat) + { + + /* ------------------------------------------------------------------ */ + /* Solve L.'x=b: x = L.' \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_ltsolve (Numeric, X, Pattern) ; + status = UMFPACK_OK ; + + } + else if (sys == UMFPACK_U_Qt) + { + + /* ------------------------------------------------------------------ */ + /* Solve UQ'x=b: x = Q (U \ b) */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* W [i] = B [i] ; */ + ASSIGN (W [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_usolve (Numeric, W, Pattern) ; + for (i = 0 ; i < n ; i++) + { + X [Cperm [i]] = W [i] ; + } + + } + else if (sys == UMFPACK_U) + { + + /* ------------------------------------------------------------------ */ + /* Solve Ux=b: x = U \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_usolve (Numeric, X, Pattern) ; + + } + else if (sys == UMFPACK_Q_Ut) + { + + /* ------------------------------------------------------------------ */ + /* Solve QU'x=b: x = U' \ Q'b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Cperm [i]] ; */ + ASSIGN (X [i], Bx, Bz, Cperm [i], Bsplit) ; + } + flops = UMF_uhsolve (Numeric, X, Pattern) ; + + } + else if (sys == UMFPACK_Q_Uat) + { + + /* ------------------------------------------------------------------ */ + /* Solve QU.'x=b: x = U.' \ Q'b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [Cperm [i]] ; */ + ASSIGN (X [i], Bx, Bz, Cperm [i], Bsplit) ; + } + flops = UMF_utsolve (Numeric, X, Pattern) ; + + } + else if (sys == UMFPACK_Ut) + { + + /* ------------------------------------------------------------------ */ + /* Solve U'x=b: x = U' \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_uhsolve (Numeric, X, Pattern) ; + + } + else if (sys == UMFPACK_Uat) + { + + /* ------------------------------------------------------------------ */ + /* Solve U'x=b: x = U' \ b */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < n ; i++) + { + /* X [i] = B [i] ; */ + ASSIGN (X [i], Bx, Bz, i, Bsplit) ; + } + flops = UMF_utsolve (Numeric, X, Pattern) ; + + } + else + { + return (UMFPACK_ERROR_invalid_system) ; + } + +#ifdef COMPLEX + /* copy the solution back, from Entry X [ ] to double Xx [ ] and Xz [ ] */ + if (AXsplit) + { + for (i = 0 ; i < n ; i++) + { + Xx [i] = REAL_COMPONENT (X [i]) ; + Xz [i] = IMAG_COMPONENT (X [i]) ; + } + } +#endif + + /* return UMFPACK_OK, or UMFPACK_WARNING_singular_matrix */ + /* Note that systems involving just L will return UMFPACK_OK */ + Info [UMFPACK_SOLVE_FLOPS] = flops ; + return (status) ; +} + + +/* ========================================================================== */ +/* === do_step ============================================================== */ +/* ========================================================================== */ + +/* Perform one step of iterative refinement, for A x = b or A' x = b */ + +PRIVATE Int do_step /* return TRUE if iterative refinement done */ +( + double omega [3], + Int step, /* which step of iterative refinement to do */ + const double B2 [ ], /* abs (B) */ + Entry X [ ], + const Entry W [ ], + const double Y [ ], + const double Z2 [ ], + Entry S [ ], + Int n, + double Info [UMFPACK_INFO] +) +{ + double last_omega [3], tau, nctau, d1, wd1, d2, wd2, xi, yix, wi, xnorm ; + Int i ; + + /* DBL_EPSILON is a standard ANSI C term defined in */ + /* It is the smallest positive x such that 1.0+x != 1.0 */ + + nctau = 1000 * n * DBL_EPSILON ; + DEBUG0 (("do_step start: nctau = %30.20e\n", nctau)) ; + ASSERT (UMF_report_vector (n, (double *) X, (double *) NULL, UMF_debug, + FALSE, FALSE) == UMFPACK_OK) ; + + /* for approximate flop count, assume d1 > tau is always true */ + /* flops += (2*ABS_FLOPS + 5) * n ; (done in UMF_solve, above) */ + + /* ---------------------------------------------------------------------- */ + /* save the last iteration in case we need to reinstate it */ + /* ---------------------------------------------------------------------- */ + + last_omega [0] = omega [0] ; + last_omega [1] = omega [1] ; + last_omega [2] = omega [2] ; + + /* ---------------------------------------------------------------------- */ + /* compute sparse backward errors: omega [1] and omega [2] */ + /* ---------------------------------------------------------------------- */ + + /* xnorm = ||x|| maxnorm */ + xnorm = 0.0 ; + for (i = 0 ; i < n ; i++) + { + /* xi = ABS (X [i]) ; */ + ABS (xi, X [i]) ; + if (SCALAR_IS_NAN (xi)) + { + xnorm = xi ; + break ; + } + /* no NaN's to consider here: */ + xnorm = MAX (xnorm, xi) ; + } + + omega [1] = 0. ; + omega [2] = 0. ; + for (i = 0 ; i < n ; i++) + { + yix = Y [i] * xnorm ; + tau = (yix + B2 [i]) * nctau ; + d1 = Z2 [i] + B2 [i] ; + /* wi = ABS (W [i]) ; */ + ABS (wi, W [i]) ; + if (SCALAR_IS_NAN (d1)) + { + omega [1] = d1 ; + omega [2] = d1 ; + break ; + } + if (SCALAR_IS_NAN (tau)) + { + omega [1] = tau ; + omega [2] = tau ; + break ; + } + if (d1 > tau) /* a double relop, but no NaN's here */ + { + wd1 = wi / d1 ; + omega [1] = MAX (omega [1], wd1) ; + } + else if (tau > 0.0) /* a double relop, but no NaN's here */ + { + d2 = Z2 [i] + yix ; + wd2 = wi / d2 ; + omega [2] = MAX (omega [2], wd2) ; + } + } + + omega [0] = omega [1] + omega [2] ; + Info [UMFPACK_OMEGA1] = omega [1] ; + Info [UMFPACK_OMEGA2] = omega [2] ; + + /* ---------------------------------------------------------------------- */ + /* stop the iterations if the backward error is small, or NaN */ + /* ---------------------------------------------------------------------- */ + + Info [UMFPACK_IR_TAKEN] = step ; + Info [UMFPACK_IR_ATTEMPTED] = step ; + + if (SCALAR_IS_NAN (omega [0])) + { + DEBUG0 (("omega[0] is NaN - done.\n")) ; + ASSERT (UMF_report_vector (n, (double *) X, (double *) NULL, UMF_debug, + FALSE, FALSE) == UMFPACK_OK) ; + return (TRUE) ; + } + + if (omega [0] < DBL_EPSILON) /* double relop, but no NaN case here */ + { + DEBUG0 (("omega[0] too small - done.\n")) ; + ASSERT (UMF_report_vector (n, (double *) X, (double *) NULL, UMF_debug, + FALSE, FALSE) == UMFPACK_OK) ; + return (TRUE) ; + } + + /* ---------------------------------------------------------------------- */ + /* stop if insufficient decrease in omega */ + /* ---------------------------------------------------------------------- */ + + /* double relop, but no NaN case here: */ + if (step > 0 && omega [0] > last_omega [0] / 2) + { + DEBUG0 (("stop refinement\n")) ; + if (omega [0] > last_omega [0]) + { + /* last iteration better than this one, reinstate it */ + DEBUG0 (("last iteration better\n")) ; + for (i = 0 ; i < n ; i++) + { + X [i] = S [i] ; + } + Info [UMFPACK_OMEGA1] = last_omega [1] ; + Info [UMFPACK_OMEGA2] = last_omega [2] ; + } + Info [UMFPACK_IR_TAKEN] = step - 1 ; + ASSERT (UMF_report_vector (n, (double *) X, (double *) NULL, UMF_debug, + FALSE, FALSE) == UMFPACK_OK) ; + return (TRUE) ; + } + + /* ---------------------------------------------------------------------- */ + /* save current solution in case we need to reinstate */ + /* ---------------------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + S [i] = X [i] ; + } + + /* ---------------------------------------------------------------------- */ + /* iterative refinement continues */ + /* ---------------------------------------------------------------------- */ + + ASSERT (UMF_report_vector (n, (double *) X, (double *) NULL, UMF_debug, + FALSE, FALSE) == UMFPACK_OK) ; + return (FALSE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_solve.h b/liboctave/UMFPACK/UMFPACK/Source/umf_solve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_solve.h @@ -0,0 +1,25 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_solve +( + Int sys, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], + double Xx [ ], + const double Bx [ ], +#ifdef COMPLEX + const double Az [ ], + double Xz [ ], + const double Bz [ ], +#endif + NumericType *Numeric, + Int irstep, + double Info [UMFPACK_INFO], + Int Pattern [ ], + double SolveWork [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.c b/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.c @@ -0,0 +1,283 @@ +/* ========================================================================== */ +/* === UMF_start_front ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Allocate the initial frontal matrix working array for a single chain. The + * front does not have to be big enough, since if it's too small it will get + * reallocated. The size computed here is just an estimate. */ + +#include "umf_internal.h" +#include "umf_grow_front.h" + +GLOBAL Int UMF_start_front /* returns TRUE if successful, FALSE otherwise */ +( + Int chain, + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) +{ + double maxbytes ; + Int fnrows_max, fncols_max, fnr2, fnc2, fsize, fcurr_size, maxfrsize, + overflow, nb, f, cdeg ; + + nb = Symbolic->nb ; + fnrows_max = Symbolic->Chain_maxrows [chain] ; + fncols_max = Symbolic->Chain_maxcols [chain] ; + + DEBUGm2 (("Start Front for chain "ID". fnrows_max "ID" fncols_max "ID"\n", + chain, fnrows_max, fncols_max)) ; + + Work->fnrows_max = fnrows_max ; + Work->fncols_max = fncols_max ; + Work->any_skip = FALSE ; + + maxbytes = sizeof (Entry) * + (double) (fnrows_max + nb) * (double) (fncols_max + nb) ; + fcurr_size = Work->fcurr_size ; + + if (Symbolic->prefer_diagonal) + { + /* Get a rough upper bound on the degree of the first pivot column in + * this front. Note that Col_degree is not maintained if diagonal + * pivoting is preferred. For most matrices, the first pivot column + * of the first frontal matrix of a new chain has only one tuple in + * it anyway, so this bound is exact in that case. */ + Int col, tpi, e, *E, *Col_tuples, *Col_tlen, *Cols ; + Tuple *tp, *tpend ; + Unit *Memory, *p ; + Element *ep ; + E = Work->E ; + Memory = Numeric->Memory ; + Col_tuples = Numeric->Lip ; + Col_tlen = Numeric->Lilen ; + col = Work->nextcand ; + tpi = Col_tuples [col] ; + tp = (Tuple *) Memory + tpi ; + tpend = tp + Col_tlen [col] ; + cdeg = 0 ; + DEBUGm3 (("\n=============== start front: col "ID" tlen "ID"\n", + col, Col_tlen [col])) ; + for ( ; tp < tpend ; tp++) + { + DEBUG1 (("Tuple ("ID","ID")\n", tp->e, tp->f)) ; + e = tp->e ; + if (!E [e]) continue ; + f = tp->f ; + p = Memory + E [e] ; + ep = (Element *) p ; + p += UNITS (Element, 1) ; + Cols = (Int *) p ; + if (Cols [f] == EMPTY) continue ; + DEBUG1 ((" nrowsleft "ID"\n", ep->nrowsleft)) ; + cdeg += ep->nrowsleft ; + } +#ifndef NDEBUG + DEBUGm3 (("start front cdeg: "ID" col "ID"\n", cdeg, col)) ; + UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ; +#endif + + /* cdeg is now the rough upper bound on the degree of the next pivot + * column. */ + + /* If AMD was called, we know the maximum number of nonzeros in any + * column of L. Use this as an upper bound for cdeg, but add 2 to + * account for a small amount of off-diagonal pivoting. */ + if (Symbolic->amd_dmax > 0) + { + cdeg = MIN (cdeg, Symbolic->amd_dmax) ; + } + + /* Increase it to account for larger columns later on. + * Also ensure that it's larger than zero. */ + cdeg += 2 ; + + /* cdeg cannot be larger than fnrows_max */ + cdeg = MIN (cdeg, fnrows_max) ; + + } + else + { + /* don't do the above cdeg computation */ + cdeg = 0 ; + } + + DEBUGm2 (("fnrows max "ID" fncols_max "ID"\n", fnrows_max, fncols_max)) ; + + /* the current frontal matrix is empty */ + ASSERT (Work->fnrows == 0 && Work->fncols == 0 && Work->fnpiv == 0) ; + + /* maximum row dimension is always odd, to avoid bad cache effects */ + ASSERT (fnrows_max >= 0) ; + ASSERT (fnrows_max % 2 == 1) ; + + /* ---------------------------------------------------------------------- + * allocate working array for current frontal matrix: + * minimum size: 1-by-1 + * maximum size: fnrows_max-by-fncols_max + * desired size: + * + * if Numeric->front_alloc_init >= 0: + * + * for unsymmetric matrices: + * Numeric->front_alloc_init * (fnrows_max-by-fncols_max) + * + * for symmetric matrices (diagonal pivoting preference, actually): + * Numeric->front_alloc_init * (fnrows_max-by-fncols_max), or + * cdeg*cdeg, whichever is smaller. + * + * if Numeric->front_alloc_init < 0: + * allocate a front of size -Numeric->front_alloc_init. + * + * Allocate the whole thing if it's small (less than 2*nb^2). Make sure the + * leading dimension of the frontal matrix is odd. + * + * Also allocate the nb-by-nb LU block, the dr-by-nb L block, and the + * nb-by-dc U block. + * ---------------------------------------------------------------------- */ + + /* get the maximum front size, avoiding integer overflow */ + overflow = INT_OVERFLOW (maxbytes) ; + if (overflow) + { + /* :: int overflow, max front size :: */ + maxfrsize = Int_MAX / sizeof (Entry) ; + } + else + { + maxfrsize = (fnrows_max + nb) * (fncols_max + nb) ; + } + ASSERT (!INT_OVERFLOW ((double) maxfrsize * sizeof (Entry))) ; + + if (Numeric->front_alloc_init < 0) + { + /* allocate a front of -Numeric->front_alloc_init entries */ + fsize = -Numeric->front_alloc_init ; + fsize = MAX (1, fsize) ; + } + else + { + if (INT_OVERFLOW (Numeric->front_alloc_init * maxbytes)) + { + /* :: int overflow, requested front size :: */ + fsize = Int_MAX / sizeof (Entry) ; + } + else + { + fsize = Numeric->front_alloc_init * maxfrsize ; + } + + if (cdeg > 0) + { + /* diagonal pivoting is in use. cdeg was computed above */ + Int fsize2 ; + + /* add the L and U blocks */ + cdeg += nb ; + + if (INT_OVERFLOW (((double) cdeg * (double) cdeg) * sizeof (Entry))) + { + /* :: int overflow, symmetric front size :: */ + fsize2 = Int_MAX / sizeof (Entry) ; + } + else + { + fsize2 = MAX (cdeg * cdeg, fcurr_size) ; + } + fsize = MIN (fsize, fsize2) ; + } + } + + fsize = MAX (fsize, 2*nb*nb) ; + + /* fsize and maxfrsize are now safe from integer overflow. They both + * include the size of the pivot blocks. */ + ASSERT (!INT_OVERFLOW ((double) fsize * sizeof (Entry))) ; + + Work->fnrows_new = 0 ; + Work->fncols_new = 0 ; + + /* desired size is fnr2-by-fnc2 (includes L and U blocks): */ + DEBUGm2 ((" fsize "ID" fcurr_size "ID"\n", fsize, fcurr_size)) ; + DEBUGm2 ((" maxfrsize "ID" fnr_curr "ID" fnc_curr "ID"\n", maxfrsize, + Work->fnr_curr, Work->fnc_curr)) ; + + if (fsize >= maxfrsize && !overflow) + { + /* max working array is small, allocate all of it */ + fnr2 = fnrows_max + nb ; + fnc2 = fncols_max + nb ; + fsize = maxfrsize ; + DEBUGm1 ((" sufficient for ("ID"+"ID")-by-("ID"+"ID")\n", + fnrows_max, nb, fncols_max, nb)) ; + } + else + { + /* allocate a smaller working array */ + if (fnrows_max <= fncols_max) + { + fnr2 = (Int) sqrt ((double) fsize) ; + /* make sure fnr2 is odd */ + fnr2 = MAX (fnr2, 1) ; + if (fnr2 % 2 == 0) fnr2++ ; + fnr2 = MIN (fnr2, fnrows_max + nb) ; + fnc2 = fsize / fnr2 ; + } + else + { + fnc2 = (Int) sqrt ((double) fsize) ; + fnc2 = MIN (fnc2, fncols_max + nb) ; + fnr2 = fsize / fnc2 ; + /* make sure fnr2 is odd */ + fnr2 = MAX (fnr2, 1) ; + if (fnr2 % 2 == 0) + { + fnr2++ ; + fnc2 = fsize / fnr2 ; + } + } + DEBUGm1 ((" smaller "ID"-by-"ID"\n", fnr2, fnc2)) ; + } + fnr2 = MIN (fnr2, fnrows_max + nb) ; + fnc2 = MIN (fnc2, fncols_max + nb) ; + ASSERT (fnr2 % 2 == 1) ; + ASSERT (fnr2 * fnc2 <= fsize) ; + + fnr2 -= nb ; + fnc2 -= nb ; + ASSERT (fnr2 >= 0) ; + ASSERT (fnc2 >= 0) ; + + if (fsize > fcurr_size) + { + DEBUGm1 ((" Grow front \n")) ; + Work->do_grow = TRUE ; + if (!UMF_grow_front (Numeric, fnr2, fnc2, Work, -1)) + { + /* since the minimum front size is 1-by-1, it would be nearly + * impossible to run out of memory here. */ + DEBUGm4 (("out of memory: start front\n")) ; + return (FALSE) ; + } + } + else + { + /* use the existing front */ + DEBUGm1 ((" existing front ok\n")) ; + Work->fnr_curr = fnr2 ; + Work->fnc_curr = fnc2 ; + Work->Flblock = Work->Flublock + nb * nb ; + Work->Fublock = Work->Flblock + nb * fnr2 ; + Work->Fcblock = Work->Fublock + nb * fnc2 ; + } + ASSERT (Work->Flblock == Work->Flublock + Work->nb*Work->nb) ; + ASSERT (Work->Fublock == Work->Flblock + Work->fnr_curr*Work->nb) ; + ASSERT (Work->Fcblock == Work->Fublock + Work->nb*Work->fnc_curr) ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.h b/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_start_front.h @@ -0,0 +1,13 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_start_front +( + Int chain, + NumericType *Numeric, + WorkType *Work, + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.c b/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.c @@ -0,0 +1,1056 @@ +/* ========================================================================== */ +/* === UMF_store_lu ========================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Store the LU factors. Called by the kernel. + Returns TRUE if successful, FALSE if out of memory. +*/ + +#include "umf_internal.h" +#include "umf_mem_alloc_head_block.h" +#include "umf_get_memory.h" + +/* ========================================================================== */ + +#ifdef DROP +GLOBAL Int UMF_store_lu_drop +#else +GLOBAL Int UMF_store_lu +#endif +( + NumericType *Numeric, + WorkType *Work +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry pivot_value ; +#ifdef DROP + double droptol ; +#endif + Entry *D, *Lval, *Uval, *Fl1, *Fl2, *Fu1, *Fu2, + *Flublock, *Flblock, *Fublock ; + Int i, k, fnr_curr, fnrows, fncols, row, col, pivrow, pivcol, *Frows, + *Fcols, *Lpattern, *Upattern, *Lpos, *Upos, llen, ulen, fnc_curr, fnpiv, + uilen, lnz, unz, nb, *Lilen, + *Uilen, *Lip, *Uip, *Li, *Ui, pivcol_position, newLchain, newUchain, + pivrow_position, p, size, lip, uip, lnzi, lnzx, unzx, lnz2i, lnz2x, + unz2i, unz2x, zero_pivot, *Pivrow, *Pivcol, kk, + Lnz [MAXNB] ; + +#ifndef NDEBUG + Int *Col_degree, *Row_degree ; +#endif + +#ifdef DROP + Int all_lnz, all_unz ; + droptol = Numeric->droptol ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + fnrows = Work->fnrows ; + fncols = Work->fncols ; + fnpiv = Work->fnpiv ; + + Lpos = Numeric->Lpos ; + Upos = Numeric->Upos ; + Lilen = Numeric->Lilen ; + Uilen = Numeric->Uilen ; + + Lip = Numeric->Lip ; + Uip = Numeric->Uip ; + D = Numeric->D ; + + Flublock = Work->Flublock ; + Flblock = Work->Flblock ; + Fublock = Work->Fublock ; + + fnr_curr = Work->fnr_curr ; + fnc_curr = Work->fnc_curr ; + Frows = Work->Frows ; + Fcols = Work->Fcols ; + +#ifndef NDEBUG + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */ + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */ +#endif + + Lpattern = Work->Lpattern ; + llen = Work->llen ; + Upattern = Work->Upattern ; + ulen = Work->ulen ; + + nb = Work->nb ; + +#ifndef NDEBUG + DEBUG1 (("\nSTORE LU: fnrows "ID + " fncols "ID"\n", fnrows, fncols)) ; + + DEBUG2 (("\nFrontal matrix, including all space:\n" + "fnr_curr "ID" fnc_curr "ID" nb "ID"\n" + "fnrows "ID" fncols "ID" fnpiv "ID"\n", + fnr_curr, fnc_curr, nb, fnrows, fncols, fnpiv)) ; + + DEBUG2 (("\nJust the active part:\n")) ; + DEBUG7 (("C block: ")) ; + UMF_dump_dense (Work->Fcblock, fnr_curr, fnrows, fncols) ; + DEBUG7 (("L block: ")) ; + UMF_dump_dense (Work->Flblock, fnr_curr, fnrows, fnpiv); + DEBUG7 (("U' block: ")) ; + UMF_dump_dense (Work->Fublock, fnc_curr, fncols, fnpiv) ; + DEBUG7 (("LU block: ")) ; + UMF_dump_dense (Work->Flublock, nb, fnpiv, fnpiv) ; + DEBUG7 (("Current frontal matrix: (prior to store LU)\n")) ; + UMF_dump_current_front (Numeric, Work, TRUE) ; +#endif + + Pivrow = Work->Pivrow ; + Pivcol = Work->Pivcol ; + + /* ---------------------------------------------------------------------- */ + /* store the columns of L */ + /* ---------------------------------------------------------------------- */ + + for (kk = 0 ; kk < fnpiv ; kk++) + { + + /* ------------------------------------------------------------------ */ + /* one more pivot row and column is being stored into L and U */ + /* ------------------------------------------------------------------ */ + + k = Work->npiv + kk ; + + /* ------------------------------------------------------------------ */ + /* find the kth pivot row and pivot column */ + /* ------------------------------------------------------------------ */ + + pivrow = Pivrow [kk] ; + pivcol = Pivcol [kk] ; + +#ifndef NDEBUG + ASSERT (pivrow >= 0 && pivrow < Work->n_row) ; + ASSERT (pivcol >= 0 && pivcol < Work->n_col) ; + + DEBUGm4 (( + "\n -------------------------------------------------------------" + "Store LU: step " ID"\n", k)) ; + ASSERT (k < MIN (Work->n_row, Work->n_col)) ; + DEBUG2 (("Store column of L, k = "ID", llen "ID"\n", k, llen)) ; + for (i = 0 ; i < llen ; i++) + { + row = Lpattern [i] ; + ASSERT (row >= 0 && row < Work->n_row) ; + DEBUG2 ((" Lpattern["ID"] "ID" Lpos "ID, i, row, Lpos [row])) ; + if (row == pivrow) DEBUG2 ((" <- pivot row")) ; + DEBUG2 (("\n")) ; + ASSERT (i == Lpos [row]) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* remove pivot row from L */ + /* ------------------------------------------------------------------ */ + + /* remove pivot row index from current column of L */ + /* if a new Lchain starts, then all entries are removed later */ + DEBUG2 (("Removing pivrow from Lpattern, k = "ID"\n", k)) ; + ASSERT (!NON_PIVOTAL_ROW (pivrow)) ; + pivrow_position = Lpos [pivrow] ; + if (pivrow_position != EMPTY) + { + /* place the last entry in the column in the */ + /* position of the pivot row index */ + ASSERT (pivrow == Lpattern [pivrow_position]) ; + row = Lpattern [--llen] ; + /* ASSERT (NON_PIVOTAL_ROW (row)) ; */ + Lpattern [pivrow_position] = row ; + Lpos [row] = pivrow_position ; + Lpos [pivrow] = EMPTY ; + } + + /* ------------------------------------------------------------------ */ + /* store the pivot value, for the diagonal matrix D */ + /* ------------------------------------------------------------------ */ + + /* kk-th column of LU block */ + Fl1 = Flublock + kk * nb ; + + /* kk-th column of L in the L block */ + Fl2 = Flblock + kk * fnr_curr ; + + /* kk-th pivot in frontal matrix located in Flublock [kk, kk] */ + pivot_value = Fl1 [kk] ; + + D [k] = pivot_value ; + zero_pivot = IS_ZERO (pivot_value) ; + + DEBUG4 (("Pivot D["ID"]=", k)) ; + EDEBUG4 (pivot_value) ; + DEBUG4 (("\n")) ; + + /* ------------------------------------------------------------------ */ + /* count nonzeros in kth column of L */ + /* ------------------------------------------------------------------ */ + + lnz = 0 ; + lnz2i = 0 ; + lnz2x = llen ; + +#ifdef DROP + all_lnz = 0 ; + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + x = Fl1 [i] ; + if (IS_ZERO (x)) continue ; + all_lnz++ ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + lnz++ ; + if (Lpos [Pivrow [i]] == EMPTY) lnz2i++ ; + } + + for (i = 0 ; i < fnrows ; i++) + { + Entry x ; + double s ; + x = Fl2 [i] ; + if (IS_ZERO (x)) continue ; + all_lnz++ ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + lnz++ ; + if (Lpos [Frows [i]] == EMPTY) lnz2i++ ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + if (IS_ZERO (Fl1 [i])) continue ; + lnz++ ; + if (Lpos [Pivrow [i]] == EMPTY) lnz2i++ ; + } + + for (i = 0 ; i < fnrows ; i++) + { + if (IS_ZERO (Fl2 [i])) continue ; + lnz++ ; + if (Lpos [Frows [i]] == EMPTY) lnz2i++ ; + } + +#endif + + lnz2x += lnz2i ; + + /* determine if we start a new Lchain or continue the old one */ + if (llen == 0 || zero_pivot) + { + /* llen == 0 means there is no prior Lchain */ + /* D [k] == 0 means the pivot column is empty */ + newLchain = TRUE ; + } + else + { + newLchain = + /* storage for starting a new Lchain */ + UNITS (Entry, lnz) + UNITS (Int, lnz) + <= + /* storage for continuing a prior Lchain */ + UNITS (Entry, lnz2x) + UNITS (Int, lnz2i) ; + } + + if (newLchain) + { + /* start a new chain for column k of L */ + DEBUG2 (("Start new Lchain, k = "ID"\n", k)) ; + + pivrow_position = EMPTY ; + + /* clear the prior Lpattern */ + for (i = 0 ; i < llen ; i++) + { + row = Lpattern [i] ; + Lpos [row] = EMPTY ; + } + llen = 0 ; + + lnzi = lnz ; + lnzx = lnz ; + } + else + { + /* continue the prior Lchain */ + DEBUG2 (("Continue Lchain, k = "ID"\n", k)) ; + lnzi = lnz2i ; + lnzx = lnz2x ; + } + + /* ------------------------------------------------------------------ */ + /* allocate space for the column of L */ + /* ------------------------------------------------------------------ */ + + size = UNITS (Int, lnzi) + UNITS (Entry, lnzx) ; + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) + { + double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ; + DEBUG4 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random garbage coll. (store LU)\n")); + } +#endif + + p = UMF_mem_alloc_head_block (Numeric, size) ; + if (!p) + { + Int r2, c2 ; + /* Do garbage collection, realloc, and try again. */ + /* Note that there are pivot rows/columns in current front. */ + if (Work->do_grow) + { + /* full compaction of current frontal matrix, since + * UMF_grow_front will be called next anyway. */ + r2 = fnrows ; + c2 = fncols ; + } + else + { + /* partial compaction. */ + r2 = MAX (fnrows, Work->fnrows_new + 1) ; + c2 = MAX (fncols, Work->fncols_new + 1) ; + } + DEBUGm3 (("get_memory from umf_store_lu:\n")) ; + if (!UMF_get_memory (Numeric, Work, size, r2, c2, TRUE)) + { + DEBUGm4 (("out of memory: store LU (1)\n")) ; + return (FALSE) ; /* out of memory */ + } + p = UMF_mem_alloc_head_block (Numeric, size) ; + if (!p) + { + DEBUGm4 (("out of memory: store LU (2)\n")) ; + return (FALSE) ; /* out of memory */ + } + /* garbage collection may have moved the current front */ + fnc_curr = Work->fnc_curr ; + fnr_curr = Work->fnr_curr ; + Flublock = Work->Flublock ; + Flblock = Work->Flblock ; + Fublock = Work->Fublock ; + Fl1 = Flublock + kk * nb ; + Fl2 = Flblock + kk * fnr_curr ; + } + + /* ------------------------------------------------------------------ */ + /* store the column of L */ + /* ------------------------------------------------------------------ */ + + lip = p ; + + Li = (Int *) (Numeric->Memory + p) ; + p += UNITS (Int, lnzi) ; + Lval = (Entry *) (Numeric->Memory + p) ; + p += UNITS (Entry, lnzx) ; + + for (i = 0 ; i < lnzx ; i++) + { + CLEAR (Lval [i]) ; + } + + /* store the numerical entries */ + + if (newLchain) + { + /* flag the first column in the Lchain by negating Lip [k] */ + lip = -lip ; + + ASSERT (llen == 0) ; + +#ifdef DROP + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + Int row2, pos ; + x = Fl1 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + row2 = Pivrow [i] ; + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + Li [pos] = row2 ; + Lval [pos] = x ; + } + + for (i = 0 ; i < fnrows ; i++) + { + Entry x ; + double s ; + Int row2, pos ; + x = Fl2 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + row2 = Frows [i] ; + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + Li [pos] = row2 ; + Lval [pos] = x ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + Int row2, pos ; + x = Fl1 [i] ; + if (IS_ZERO (x)) continue ; + row2 = Pivrow [i] ; + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + Li [pos] = row2 ; + Lval [pos] = x ; + } + + for (i = 0 ; i < fnrows ; i++) + { + Entry x ; + Int row2, pos ; + x = Fl2 [i] ; + if (IS_ZERO (x)) continue ; + row2 = Frows [i] ; + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + Li [pos] = row2 ; + Lval [pos] = x ; + } + +#endif + + } + else + { + ASSERT (llen > 0) ; + +#ifdef DROP + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + Int row2, pos ; + x = Fl1 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + row2 = Pivrow [i] ; + pos = Lpos [row2] ; + if (pos == EMPTY) + { + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + *Li++ = row2 ; + } + Lval [pos] = x ; + } + + for (i = 0 ; i < fnrows ; i++) + { + Entry x ; + double s ; + Int row2, pos ; + x = Fl2 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + row2 = Frows [i] ; + pos = Lpos [row2] ; + if (pos == EMPTY) + { + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + *Li++ = row2 ; + } + Lval [pos] = x ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + Int row2, pos ; + x = Fl1 [i] ; + if (IS_ZERO (x)) continue ; + row2 = Pivrow [i] ; + pos = Lpos [row2] ; + if (pos == EMPTY) + { + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + *Li++ = row2 ; + } + Lval [pos] = x ; + } + + for (i = 0 ; i < fnrows ; i++) + { + Entry x ; + Int row2, pos ; + x = Fl2 [i] ; + if (IS_ZERO (x)) continue ; + row2 = Frows [i] ; + pos = Lpos [row2] ; + if (pos == EMPTY) + { + pos = llen++ ; + Lpattern [pos] = row2 ; + Lpos [row2] = pos ; + *Li++ = row2 ; + } + Lval [pos] = x ; + } + +#endif + + } + DEBUG4 (("llen "ID" lnzx "ID"\n", llen, lnzx)) ; + ASSERT (llen == lnzx) ; + ASSERT (lnz <= llen) ; + DEBUG4 (("lnz "ID" \n", lnz)) ; + +#ifdef DROP + + DEBUG4 (("all_lnz "ID" \n", all_lnz)) ; + ASSERT (lnz <= all_lnz) ; + Numeric->lnz += lnz ; + Numeric->all_lnz += all_lnz ; + Lnz [kk] = all_lnz ; + +#else + + Numeric->lnz += lnz ; + Numeric->all_lnz += lnz ; + Lnz [kk] = lnz ; +#endif + + Numeric->nLentries += lnzx ; + Work->llen = llen ; + Numeric->isize += lnzi ; + + /* ------------------------------------------------------------------ */ + /* the pivot column is fully assembled and scaled, and is now the */ + /* k-th column of L */ + /* ------------------------------------------------------------------ */ + + Lpos [pivrow] = pivrow_position ; /* not aliased */ + Lip [pivcol] = lip ; /* aliased with Col_tuples */ + Lilen [pivcol] = lnzi ; /* aliased with Col_tlen */ + + } + + /* ---------------------------------------------------------------------- */ + /* store the rows of U */ + /* ---------------------------------------------------------------------- */ + + for (kk = 0 ; kk < fnpiv ; kk++) + { + + /* ------------------------------------------------------------------ */ + /* one more pivot row and column is being stored into L and U */ + /* ------------------------------------------------------------------ */ + + k = Work->npiv + kk ; + + /* ------------------------------------------------------------------ */ + /* find the kth pivot row and pivot column */ + /* ------------------------------------------------------------------ */ + + pivrow = Pivrow [kk] ; + pivcol = Pivcol [kk] ; + +#ifndef NDEBUG + ASSERT (pivrow >= 0 && pivrow < Work->n_row) ; + ASSERT (pivcol >= 0 && pivcol < Work->n_col) ; + + DEBUG2 (("Store row of U, k = "ID", ulen "ID"\n", k, ulen)) ; + for (i = 0 ; i < ulen ; i++) + { + col = Upattern [i] ; + DEBUG2 ((" Upattern["ID"] "ID, i, col)) ; + if (col == pivcol) DEBUG2 ((" <- pivot col")) ; + DEBUG2 (("\n")) ; + ASSERT (col >= 0 && col < Work->n_col) ; + ASSERT (i == Upos [col]) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* get the pivot value, for the diagonal matrix D */ + /* ------------------------------------------------------------------ */ + + zero_pivot = IS_ZERO (D [k]) ; + + /* ------------------------------------------------------------------ */ + /* count the nonzeros in the row of U */ + /* ------------------------------------------------------------------ */ + + /* kk-th row of U in the LU block */ + Fu1 = Flublock + kk ; + + /* kk-th row of U in the U block */ + Fu2 = Fublock + kk * fnc_curr ; + + unz = 0 ; + unz2i = 0 ; + unz2x = ulen ; + DEBUG2 (("unz2x is "ID", lnzx "ID"\n", unz2x, lnzx)) ; + + /* if row k does not end a Uchain, pivcol not included in ulen */ + ASSERT (!NON_PIVOTAL_COL (pivcol)) ; + pivcol_position = Upos [pivcol] ; + if (pivcol_position != EMPTY) + { + unz2x-- ; + DEBUG2 (("(exclude pivcol) unz2x is now "ID"\n", unz2x)) ; + } + + ASSERT (unz2x >= 0) ; + +#ifdef DROP + all_unz = 0 ; + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + x = Fu1 [i*nb] ; + if (IS_ZERO (x)) continue ; + all_unz++ ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + unz++ ; + if (Upos [Pivcol [i]] == EMPTY) unz2i++ ; + } + + for (i = 0 ; i < fncols ; i++) + { + Entry x ; + double s ; + x = Fu2 [i] ; + if (IS_ZERO (x)) continue ; + all_unz++ ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + unz++ ; + if (Upos [Fcols [i]] == EMPTY) unz2i++ ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + if (IS_ZERO (Fu1 [i*nb])) continue ; + unz++ ; + if (Upos [Pivcol [i]] == EMPTY) unz2i++ ; + } + + for (i = 0 ; i < fncols ; i++) + { + if (IS_ZERO (Fu2 [i])) continue ; + unz++ ; + if (Upos [Fcols [i]] == EMPTY) unz2i++ ; + } + +#endif + + unz2x += unz2i ; + + ASSERT (IMPLIES (k == 0, ulen == 0)) ; + + /* determine if we start a new Uchain or continue the old one */ + if (ulen == 0 || zero_pivot) + { + /* ulen == 0 means there is no prior Uchain */ + /* D [k] == 0 means the matrix is singular (pivot row might */ + /* not be empty, however, but start a new Uchain to prune zero */ + /* entries for the deg > 0 test in UMF_u*solve) */ + newUchain = TRUE ; + } + else + { + newUchain = + /* approximate storage for starting a new Uchain */ + UNITS (Entry, unz) + UNITS (Int, unz) + <= + /* approximate storage for continuing a prior Uchain */ + UNITS (Entry, unz2x) + UNITS (Int, unz2i) ; + + /* this would be exact, except for the Int to Unit rounding, */ + /* because the Upattern is stored only at the end of the Uchain */ + } + + /* ------------------------------------------------------------------ */ + /* allocate space for the row of U */ + /* ------------------------------------------------------------------ */ + + size = 0 ; + if (newUchain) + { + /* store the pattern of the last row in the prior Uchain */ + size += UNITS (Int, ulen) ; + unzx = unz ; + } + else + { + unzx = unz2x ; + } + size += UNITS (Entry, unzx) ; + +#ifndef NDEBUG + UMF_allocfail = FALSE ; + if (UMF_gprob > 0) + { + double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ; + DEBUG4 (("Check random %e %e\n", rrr, UMF_gprob)) ; + UMF_allocfail = rrr < UMF_gprob ; + if (UMF_allocfail) DEBUGm2 (("Random garbage coll. (store LU)\n")); + } +#endif + + p = UMF_mem_alloc_head_block (Numeric, size) ; + if (!p) + { + Int r2, c2 ; + /* Do garbage collection, realloc, and try again. */ + /* Note that there are pivot rows/columns in current front. */ + if (Work->do_grow) + { + /* full compaction of current frontal matrix, since + * UMF_grow_front will be called next anyway. */ + r2 = fnrows ; + c2 = fncols ; + } + else + { + /* partial compaction. */ + r2 = MAX (fnrows, Work->fnrows_new + 1) ; + c2 = MAX (fncols, Work->fncols_new + 1) ; + } + DEBUGm3 (("get_memory from umf_store_lu:\n")) ; + if (!UMF_get_memory (Numeric, Work, size, r2, c2, TRUE)) + { + /* :: get memory, column of L :: */ + DEBUGm4 (("out of memory: store LU (1)\n")) ; + return (FALSE) ; /* out of memory */ + } + p = UMF_mem_alloc_head_block (Numeric, size) ; + if (!p) + { + /* :: out of memory, column of U :: */ + DEBUGm4 (("out of memory: store LU (2)\n")) ; + return (FALSE) ; /* out of memory */ + } + /* garbage collection may have moved the current front */ + fnc_curr = Work->fnc_curr ; + fnr_curr = Work->fnr_curr ; + Flublock = Work->Flublock ; + Flblock = Work->Flblock ; + Fublock = Work->Fublock ; + Fu1 = Flublock + kk ; + Fu2 = Fublock + kk * fnc_curr ; + } + + /* ------------------------------------------------------------------ */ + /* store the row of U */ + /* ------------------------------------------------------------------ */ + + uip = p ; + + if (newUchain) + { + /* starting a new Uchain - flag this by negating Uip [k] */ + uip = -uip ; + DEBUG2 (("Start new Uchain, k = "ID"\n", k)) ; + + pivcol_position = EMPTY ; + + /* end the prior Uchain */ + /* save the current Upattern, and then */ + /* clear it and start a new Upattern */ + DEBUG2 (("Ending prior chain, k-1 = "ID"\n", k-1)) ; + uilen = ulen ; + Ui = (Int *) (Numeric->Memory + p) ; + Numeric->isize += ulen ; + p += UNITS (Int, ulen) ; + for (i = 0 ; i < ulen ; i++) + { + col = Upattern [i] ; + ASSERT (col >= 0 && col < Work->n_col) ; + Upos [col] = EMPTY ; + Ui [i] = col ; + } + + ulen = 0 ; + + } + else + { + /* continue the prior Uchain */ + DEBUG2 (("Continue Uchain, k = "ID"\n", k)) ; + ASSERT (k > 0) ; + + /* remove pivot col index from current row of U */ + /* if a new Uchain starts, then all entries are removed later */ + DEBUG2 (("Removing pivcol from Upattern, k = "ID"\n", k)) ; + + if (pivcol_position != EMPTY) + { + /* place the last entry in the row in the */ + /* position of the pivot col index */ + ASSERT (pivcol == Upattern [pivcol_position]) ; + col = Upattern [--ulen] ; + ASSERT (col >= 0 && col < Work->n_col) ; + Upattern [pivcol_position] = col ; + Upos [col] = pivcol_position ; + Upos [pivcol] = EMPTY ; + } + + /* this row continues the Uchain. Keep track of how much */ + /* to trim from the k-th length to get the length of the */ + /* (k-1)st row of U */ + uilen = unz2i ; + + } + + Uval = (Entry *) (Numeric->Memory + p) ; + /* p += UNITS (Entry, unzx), no need to increment p */ + + for (i = 0 ; i < unzx ; i++) + { + CLEAR (Uval [i]) ; + } + + if (newUchain) + { + ASSERT (ulen == 0) ; + +#ifdef DROP + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + Int col2, pos ; + x = Fu1 [i*nb] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + col2 = Pivcol [i] ; + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + Uval [pos] = x ; + } + + for (i = 0 ; i < fncols ; i++) + { + Entry x ; + double s ; + Int col2, pos ; + x = Fu2 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + col2 = Fcols [i] ; + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + Uval [pos] = x ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + Int col2, pos ; + x = Fu1 [i*nb] ; + if (IS_ZERO (x)) continue ; + col2 = Pivcol [i] ; + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + Uval [pos] = x ; + } + + for (i = 0 ; i < fncols ; i++) + { + Entry x ; + Int col2, pos ; + x = Fu2 [i] ; + if (IS_ZERO (x)) continue ; + col2 = Fcols [i] ; + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + Uval [pos] = x ; + } + +#endif + + } + else + { + + ASSERT (ulen > 0) ; + + /* store the numerical entries and find new nonzeros */ + +#ifdef DROP + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + double s ; + Int col2, pos ; + x = Fu1 [i*nb] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + col2 = Pivcol [i] ; + pos = Upos [col2] ; + if (pos == EMPTY) + { + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + } + Uval [pos] = x ; + } + + for (i = 0 ; i < fncols ; i++) + { + Entry x ; + double s ; + Int col2, pos ; + x = Fu2 [i] ; + APPROX_ABS (s, x) ; + if (s <= droptol) continue ; + col2 = Fcols [i] ; + pos = Upos [col2] ; + if (pos == EMPTY) + { + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + } + Uval [pos] = x ; + } + +#else + + for (i = kk + 1 ; i < fnpiv ; i++) + { + Entry x ; + Int col2, pos ; + x = Fu1 [i*nb] ; + if (IS_ZERO (x)) continue ; + col2 = Pivcol [i] ; + pos = Upos [col2] ; + if (pos == EMPTY) + { + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + } + Uval [pos] = x ; + } + + for (i = 0 ; i < fncols ; i++) + { + Entry x ; + Int col2, pos ; + x = Fu2 [i] ; + if (IS_ZERO (x)) continue ; + col2 = Fcols [i] ; + pos = Upos [col2] ; + if (pos == EMPTY) + { + pos = ulen++ ; + Upattern [pos] = col2 ; + Upos [col2] = pos ; + } + Uval [pos] = x ; + } + +#endif + + } + + ASSERT (ulen == unzx) ; + ASSERT (unz <= ulen) ; + DEBUG4 (("unz "ID" \n", unz)) ; + +#ifdef DROP + + DEBUG4 (("all_unz "ID" \n", all_unz)) ; + ASSERT (unz <= all_unz) ; + Numeric->unz += unz ; + Numeric->all_unz += all_unz ; + /* count the "true" flops, based on LU pattern only */ + Numeric->flops += DIV_FLOPS * Lnz [kk] /* scale pivot column */ + + MULTSUB_FLOPS * (Lnz [kk] * all_unz) ; /* outer product */ + +#else + + Numeric->unz += unz ; + Numeric->all_unz += unz ; + /* count the "true" flops, based on LU pattern only */ + Numeric->flops += DIV_FLOPS * Lnz [kk] /* scale pivot column */ + + MULTSUB_FLOPS * (Lnz [kk] * unz) ; /* outer product */ +#endif + + Numeric->nUentries += unzx ; + Work->ulen = ulen ; + DEBUG1 (("Work->ulen = "ID" at end of pivot step, k: "ID"\n", ulen, k)); + + /* ------------------------------------------------------------------ */ + /* the pivot row is the k-th row of U */ + /* ------------------------------------------------------------------ */ + + Upos [pivcol] = pivcol_position ; /* not aliased */ + Uip [pivrow] = uip ; /* aliased with Row_tuples */ + Uilen [pivrow] = uilen ; /* aliased with Row_tlen */ + + } + + /* ---------------------------------------------------------------------- */ + /* no more pivots in frontal working array */ + /* ---------------------------------------------------------------------- */ + + Work->npiv += fnpiv ; + Work->fnpiv = 0 ; + Work->fnzeros = 0 ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.h b/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_store_lu.h @@ -0,0 +1,17 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_store_lu +( + NumericType *Numeric, + WorkType *Work +) ; + +GLOBAL Int UMF_store_lu_drop +( + NumericType *Numeric, + WorkType *Work +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.c b/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.c @@ -0,0 +1,45 @@ +/* ========================================================================== */ +/* === UMF_symbolic_usage =================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Returns the final size of the Symbolic object, in Units */ + +#include "umf_internal.h" + +GLOBAL double UMF_symbolic_usage +( + Int n_row, + Int n_col, + Int nchains, + Int nfr, + Int esize, /* zero if no dense rows. Otherwise, equal to the + * number of non-singleton, non-empty columns */ + Int prefer_diagonal +) +{ + double units ; + + units = + DUNITS (SymbolicType, 1) /* Symbolic structure */ + + 2 * DUNITS (Int, n_col+1) /* Cperm_init, Cdeg */ + + 2 * DUNITS (Int, n_row+1) /* Rperm_init, Rdeg */ + + 3 * DUNITS (Int, nchains+1) /* Chain_ */ + + 4 * DUNITS (Int, nfr+1) ; /* Front_ */ + + /* if dense rows are present */ + units += DUNITS (Int, esize) ; /* Esize */ + + /* for diagonal pivoting */ + if (prefer_diagonal) + { + units += DUNITS (Int, n_col+1) ; /* Diagonal_map */ + } + + return (units) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.h b/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_symbolic_usage.h @@ -0,0 +1,15 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL double UMF_symbolic_usage +( + Int n_row, + Int n_col, + Int nchains, + Int nfr, + Int esize, + Int prefer_diagonal +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.c b/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.c @@ -0,0 +1,400 @@ +/* ========================================================================== */ +/* === UMF_transpose ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Not user-callable. Computes a permuted transpose, R = (A (P,Q(1:nq)))' in + MATLAB notation, where R is in column-form. A is n_row-by-n_col, the + row-form matrix R is n_row-by-nq, where nq <= n_col. A may be singular. + The complex version can do transpose (') or array transpose (.'). + + Uses Gustavson's method (Two Fast Algorithms for Sparse Matrices: + Multiplication and Permuted Transposition, ACM Trans. on Math. Softw., + vol 4, no 3, pp. 250-269). +*/ + +#include "umf_internal.h" +#include "umf_is_permutation.h" + +GLOBAL Int UMF_transpose +( + Int n_row, /* A is n_row-by-n_col */ + Int n_col, + const Int Ap [ ], /* size n_col+1 */ + const Int Ai [ ], /* size nz = Ap [n_col] */ + const double Ax [ ], /* size nz if present */ + + const Int P [ ], /* P [k] = i means original row i is kth row in A(P,Q)*/ + /* P is identity if not present */ + /* size n_row, if present */ + + const Int Q [ ], /* Q [k] = j means original col j is kth col in A(P,Q)*/ + /* Q is identity if not present */ + /* size nq, if present */ + Int nq, /* size of Q, ignored if Q is (Int *) NULL */ + + /* output matrix: Rp, Ri, Rx, and Rz: */ + Int Rp [ ], /* size n_row+1 */ + Int Ri [ ], /* size nz */ + double Rx [ ], /* size nz, if present */ + + Int W [ ], /* size max (n_row,n_col) workspace */ + + Int check /* if true, then check inputs */ +#ifdef COMPLEX + , const double Az [ ] /* size nz */ + , double Rz [ ] /* size nz */ + , Int do_conjugate /* if true, then do conjugate transpose */ + /* otherwise, do array transpose */ +#endif +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int i, j, k, p, bp, newj, do_values ; +#ifdef COMPLEX + Int split ; +#endif + + /* ---------------------------------------------------------------------- */ + /* check inputs */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + Int nz ; + ASSERT (n_col >= 0) ; + nz = (Ap != (Int *) NULL) ? Ap [n_col] : 0 ; + DEBUG2 (("UMF_transpose: "ID"-by-"ID" nz "ID"\n", n_row, n_col, nz)) ; +#endif + + if (check) + { + /* UMFPACK_symbolic skips this check */ + /* UMFPACK_transpose always does this check */ + if (!Ai || !Ap || !Ri || !Rp || !W) + { + return (UMFPACK_ERROR_argument_missing) ; + } + if (n_row <= 0 || n_col <= 0) /* n_row,n_col must be > 0 */ + { + return (UMFPACK_ERROR_n_nonpositive) ; + } + if (!UMF_is_permutation (P, W, n_row, n_row) || + !UMF_is_permutation (Q, W, nq, nq)) + { + return (UMFPACK_ERROR_invalid_permutation) ; + } + if (!AMD_valid (n_row, n_col, Ap, Ai)) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + } + +#ifndef NDEBUG + DEBUG2 (("UMF_transpose, input matrix:\n")) ; + UMF_dump_col_matrix (Ax, +#ifdef COMPLEX + Az, +#endif + Ai, Ap, n_row, n_col, nz) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* count the entries in each row of A */ + /* ---------------------------------------------------------------------- */ + + /* use W as workspace for RowCount */ + + for (i = 0 ; i < n_row ; i++) + { + W [i] = 0 ; + Rp [i] = 0 ; + } + + if (Q != (Int *) NULL) + { + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + ASSERT (i >= 0 && i < n_row) ; + W [i]++ ; + } + } + } + else + { + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + i = Ai [p] ; + ASSERT (i >= 0 && i < n_row) ; + W [i]++ ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* compute the row pointers for R = A (P,Q) */ + /* ---------------------------------------------------------------------- */ + + if (P != (Int *) NULL) + { + Rp [0] = 0 ; + for (k = 0 ; k < n_row ; k++) + { + i = P [k] ; + ASSERT (i >= 0 && i < n_row) ; + Rp [k+1] = Rp [k] + W [i] ; + } + for (k = 0 ; k < n_row ; k++) + { + i = P [k] ; + ASSERT (i >= 0 && i < n_row) ; + W [i] = Rp [k] ; + } + } + else + { + Rp [0] = 0 ; + for (i = 0 ; i < n_row ; i++) + { + Rp [i+1] = Rp [i] + W [i] ; + } + for (i = 0 ; i < n_row ; i++) + { + W [i] = Rp [i] ; + } + } + ASSERT (Rp [n_row] <= Ap [n_col]) ; + + /* at this point, W holds the permuted row pointers */ + + /* ---------------------------------------------------------------------- */ + /* construct the row form of B */ + /* ---------------------------------------------------------------------- */ + + do_values = Ax && Rx ; + +#ifdef COMPLEX + split = SPLIT (Az) && SPLIT (Rz) ; + + if (do_conjugate && do_values) + { + if (Q != (Int *) NULL) + { + if (split) + { + /* R = A (P,Q)' */ + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = newj ; + Rx [bp] = Ax [p] ; + Rz [bp] = -Az [p] ; + } + } + } + else + { + /* R = A (P,Q)' (merged complex values) */ + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = newj ; + Rx [2*bp] = Ax [2*p] ; + Rx [2*bp+1] = -Ax [2*p+1] ; + } + } + } + } + else + { + if (split) + { + /* R = A (P,:)' */ + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = j ; + Rx [bp] = Ax [p] ; + Rz [bp] = -Az [p] ; + } + } + } + else + { + /* R = A (P,:)' (merged complex values) */ + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = j ; + Rx [2*bp] = Ax [2*p] ; + Rx [2*bp+1] = -Ax [2*p+1] ; + } + } + } + } + } + else +#endif + { + if (Q != (Int *) NULL) + { + if (do_values) + { +#ifdef COMPLEX + if (split) +#endif + { + /* R = A (P,Q).' */ + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = newj ; + Rx [bp] = Ax [p] ; +#ifdef COMPLEX + Rz [bp] = Az [p] ; +#endif + } + } + } +#ifdef COMPLEX + else + { + /* R = A (P,Q).' (merged complex values) */ + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = newj ; + Rx [2*bp] = Ax [2*p] ; + Rx [2*bp+1] = Ax [2*p+1] ; + } + } + } +#endif + } + else + { + /* R = pattern of A (P,Q).' */ + for (newj = 0 ; newj < nq ; newj++) + { + j = Q [newj] ; + ASSERT (j >= 0 && j < n_col) ; + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + Ri [W [Ai [p]]++] = newj ; + } + } + } + } + else + { + if (do_values) + { +#ifdef COMPLEX + if (split) +#endif + { + /* R = A (P,:).' */ + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = j ; + Rx [bp] = Ax [p] ; +#ifdef COMPLEX + Rz [bp] = Az [p] ; +#endif + } + } + } +#ifdef COMPLEX + else + { + /* R = A (P,:).' (merged complex values) */ + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + bp = W [Ai [p]]++ ; + Ri [bp] = j ; + Rx [2*bp] = Ax [2*p] ; + Rx [2*bp+1] = Ax [2*p+1] ; + } + } + } +#endif + } + else + { + /* R = pattern of A (P,:).' */ + for (j = 0 ; j < n_col ; j++) + { + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + Ri [W [Ai [p]]++] = j ; + } + } + } + } + } + +#ifndef NDEBUG + for (k = 0 ; k < n_row ; k++) + { + if (P != (Int *) NULL) + { + i = P [k] ; + } + else + { + i = k ; + } + DEBUG3 ((ID": W[i] "ID" Rp[k+1] "ID"\n", i, W [i], Rp [k+1])) ; + ASSERT (W [i] == Rp [k+1]) ; + } + DEBUG2 (("UMF_transpose, output matrix:\n")) ; + UMF_dump_col_matrix (Rx, +#ifdef COMPLEX + Rz, +#endif + Ri, Rp, n_col, n_row, Rp [n_row]) ; + ASSERT (AMD_valid (n_col, n_row, Rp, Ri)) ; +#endif + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.h b/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_transpose.h @@ -0,0 +1,27 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_transpose +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], + const Int P [ ], + const Int Q [ ], + Int nq, + Int Rp [ ], + Int Ri [ ], + double Rx [ ], + Int W [ ], + Int check +#ifdef COMPLEX + , const double Az [ ] + , double Rz [ ] + , Int do_conjugate +#endif +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.c b/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.c @@ -0,0 +1,428 @@ +/* ========================================================================== */ +/* === UMF_triplet ========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Not user callable. Converts triplet input to column-oriented form. + Duplicate entries may exist (they are summed in the output). The columns + of the column-oriented form are in sorted order. The input is not modified. + Returns 1 if OK, 0 if an error occurred. + + Compiled into four different routines for each version (di, dl, zi, zl), + for a total of 16 different routines. +*/ + +#include "umf_internal.h" + +#ifdef DO_MAP +#ifdef DO_VALUES +GLOBAL Int UMF_triplet_map_x +#else +GLOBAL Int UMF_triplet_map_nox +#endif +#else +#ifdef DO_VALUES +GLOBAL Int UMF_triplet_nomap_x +#else +GLOBAL Int UMF_triplet_nomap_nox +#endif +#endif +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], /* size nz */ + const Int Tj [ ], /* size nz */ + Int Ap [ ], /* size n_col + 1 */ + Int Ai [ ], /* size nz */ + Int Rp [ ], /* size n_row + 1 */ + Int Rj [ ], /* size nz */ + Int W [ ], /* size max (n_row, n_col) */ + Int RowCount [ ] /* size n_row */ +#ifdef DO_VALUES + , const double Tx [ ] /* size nz */ + , double Ax [ ] /* size nz */ + , double Rx [ ] /* size nz */ +#ifdef COMPLEX + , const double Tz [ ] /* size nz */ + , double Az [ ] /* size nz */ + , double Rz [ ] /* size nz */ +#endif +#endif +#ifdef DO_MAP + , Int Map [ ] /* size nz */ + , Int Map2 [ ] /* size nz */ +#endif +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int i, j, k, p, cp, p1, p2, pdest, pj ; +#ifdef DO_MAP + Int duplicates ; +#endif +#ifdef DO_VALUES +#ifdef COMPLEX + Int split = SPLIT (Tz) && SPLIT (Az) && SPLIT (Rz) ; +#endif +#endif + + /* ---------------------------------------------------------------------- */ + /* count the entries in each row (also counting duplicates) */ + /* ---------------------------------------------------------------------- */ + + /* use W as workspace for row counts (including duplicates) */ + for (i = 0 ; i < n_row ; i++) + { + W [i] = 0 ; + } + + for (k = 0 ; k < nz ; k++) + { + i = Ti [k] ; + j = Tj [k] ; + if (i < 0 || i >= n_row || j < 0 || j >= n_col) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + W [i]++ ; +#ifndef NDEBUG + DEBUG1 ((ID " triplet: "ID" "ID" ", k, i, j)) ; +#ifdef DO_VALUES + { + Entry tt ; + ASSIGN (tt, Tx, Tz, k, split) ; + EDEBUG2 (tt) ; + DEBUG1 (("\n")) ; + } +#endif +#endif + } + + /* ---------------------------------------------------------------------- */ + /* compute the row pointers */ + /* ---------------------------------------------------------------------- */ + + Rp [0] = 0 ; + for (i = 0 ; i < n_row ; i++) + { + Rp [i+1] = Rp [i] + W [i] ; + W [i] = Rp [i] ; + } + + /* W is now equal to the row pointers */ + + /* ---------------------------------------------------------------------- */ + /* construct the row form */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < nz ; k++) + { + p = W [Ti [k]]++ ; +#ifdef DO_MAP + Map [k] = p ; +#endif + Rj [p] = Tj [k] ; +#ifdef DO_VALUES +#ifdef COMPLEX + if (split) + { + Rx [p] = Tx [k] ; + Rz [p] = Tz [k] ; + } + else + { + Rx [2*p ] = Tx [2*k ] ; + Rx [2*p+1] = Tx [2*k+1] ; + } +#else + Rx [p] = Tx [k] ; +#endif +#endif + } + + /* Rp stays the same, but W [i] is advanced to the start of row i+1 */ + +#ifndef NDEBUG + for (i = 0 ; i < n_row ; i++) + { + ASSERT (W [i] == Rp [i+1]) ; + } +#ifdef DO_MAP + for (k = 0 ; k < nz ; k++) + { + /* make sure that kth triplet is mapped correctly */ + p = Map [k] ; + DEBUG1 (("First row map: Map ["ID"] = "ID"\n", k, p)) ; + i = Ti [k] ; + j = Tj [k] ; + ASSERT (j == Rj [p]) ; + ASSERT (Rp [i] <= p && p < Rp [i+1]) ; + } +#endif +#endif + + /* ---------------------------------------------------------------------- */ + /* sum up duplicates */ + /* ---------------------------------------------------------------------- */ + + /* use W [j] to hold position in Ri/Rx/Rz of a_ij, for row i [ */ + + for (j = 0 ; j < n_col ; j++) + { + W [j] = EMPTY ; + } + +#ifdef DO_MAP + duplicates = FALSE ; +#endif + + for (i = 0 ; i < n_row ; i++) + { + p1 = Rp [i] ; + p2 = Rp [i+1] ; + pdest = p1 ; + /* At this point, W [j] < p1 holds true for all columns j, */ + /* because Ri/Rx/Rz is stored in row oriented order. */ +#ifndef NDEBUG + if (UMF_debug >= -2) + { + for (j = 0 ; j < n_col ; j++) + { + ASSERT (W [j] < p1) ; + } + } +#endif + for (p = p1 ; p < p2 ; p++) + { + j = Rj [p] ; + ASSERT (j >= 0 && j < n_col) ; + pj = W [j] ; + if (pj >= p1) + { + /* this column index, j, is already in row i, at position pj */ + ASSERT (pj < p) ; + ASSERT (Rj [pj] == j) ; +#ifdef DO_MAP + Map2 [p] = pj ; + duplicates = TRUE ; +#endif +#ifdef DO_VALUES + /* sum the entry */ +#ifdef COMPLEX + if (split) + { + Rx [pj] += Rx [p] ; + Rz [pj] += Rz [p] ; + } + else + { + Rx[2*pj ] += Rx[2*p ] ; + Rx[2*pj+1] += Rx[2*p+1] ; + } +#else + Rx [pj] += Rx [p] ; +#endif +#endif + } + else + { + /* keep the entry */ + /* also keep track in W[j] of position of a_ij for case above */ + W [j] = pdest ; +#ifdef DO_MAP + Map2 [p] = pdest ; +#endif + /* no need to move the entry if pdest is equal to p */ + if (pdest != p) + { + Rj [pdest] = j ; +#ifdef DO_VALUES +#ifdef COMPLEX + if (split) + { + Rx [pdest] = Rx [p] ; + Rz [pdest] = Rz [p] ; + } + else + { + Rx [2*pdest ] = Rx [2*p ] ; + Rx [2*pdest+1] = Rx [2*p+1] ; + } +#else + Rx [pdest] = Rx [p] ; +#endif +#endif + } + pdest++ ; + } + } + RowCount [i] = pdest - p1 ; + } + + /* done using W for position of a_ij ] */ + + /* ---------------------------------------------------------------------- */ + /* merge Map and Map2 into a single Map */ + /* ---------------------------------------------------------------------- */ + +#ifdef DO_MAP + if (duplicates) + { + for (k = 0 ; k < nz ; k++) + { + Map [k] = Map2 [Map [k]] ; + } + } +#ifndef NDEBUG + else + { + /* no duplicates, so no need to recompute Map */ + for (k = 0 ; k < nz ; k++) + { + ASSERT (Map2 [k] == k) ; + } + } + for (k = 0 ; k < nz ; k++) + { + /* make sure that kth triplet is mapped correctly */ + p = Map [k] ; + DEBUG1 (("Second row map: Map ["ID"] = "ID"\n", k, p)) ; + i = Ti [k] ; + j = Tj [k] ; + ASSERT (j == Rj [p]) ; + ASSERT (Rp [i] <= p && p < Rp [i+1]) ; + } +#endif +#endif + + /* now the kth triplet maps to p = Map [k], and thus to Rj/Rx [p] */ + + /* ---------------------------------------------------------------------- */ + /* count the entries in each column */ + /* ---------------------------------------------------------------------- */ + + /* [ use W as work space for column counts of A */ + for (j = 0 ; j < n_col ; j++) + { + W [j] = 0 ; + } + + for (i = 0 ; i < n_row ; i++) + { + for (p = Rp [i] ; p < Rp [i] + RowCount [i] ; p++) + { + j = Rj [p] ; + ASSERT (j >= 0 && j < n_col) ; + W [j]++ ; + } + } + + /* ---------------------------------------------------------------------- */ + /* create the column pointers */ + /* ---------------------------------------------------------------------- */ + + Ap [0] = 0 ; + for (j = 0 ; j < n_col ; j++) + { + Ap [j+1] = Ap [j] + W [j] ; + } + /* done using W as workspace for column counts of A ] */ + + for (j = 0 ; j < n_col ; j++) + { + W [j] = Ap [j] ; + } + + /* ---------------------------------------------------------------------- */ + /* construct the column form */ + /* ---------------------------------------------------------------------- */ + + for (i = 0 ; i < n_row ; i++) + { + for (p = Rp [i] ; p < Rp [i] + RowCount [i] ; p++) + { + cp = W [Rj [p]]++ ; +#ifdef DO_MAP + Map2 [p] = cp ; +#endif + Ai [cp] = i ; +#ifdef DO_VALUES +#ifdef COMPLEX + if (split) + { + Ax [cp] = Rx [p] ; + Az [cp] = Rz [p] ; + } + else + { + Ax [2*cp ] = Rx [2*p ] ; + Ax [2*cp+1] = Rx [2*p+1] ; + } +#else + Ax [cp] = Rx [p] ; +#endif +#endif + } + } + + /* ---------------------------------------------------------------------- */ + /* merge Map and Map2 into a single Map */ + /* ---------------------------------------------------------------------- */ + +#ifdef DO_MAP + for (k = 0 ; k < nz ; k++) + { + Map [k] = Map2 [Map [k]] ; + } +#endif + + /* now the kth triplet maps to p = Map [k], and thus to Ai/Ax [p] */ + +#ifndef NDEBUG + for (j = 0 ; j < n_col ; j++) + { + ASSERT (W [j] == Ap [j+1]) ; + } + + UMF_dump_col_matrix ( +#ifdef DO_VALUES + Ax, +#ifdef COMPLEX + Az, +#endif +#else + (double *) NULL, +#ifdef COMPLEX + (double *) NULL, +#endif +#endif + Ai, Ap, n_row, n_col, nz) ; + +#ifdef DO_MAP + for (k = 0 ; k < nz ; k++) + { + /* make sure that kth triplet is mapped correctly */ + p = Map [k] ; + DEBUG1 (("Col map: Map ["ID"] = "ID"\t", k, p)) ; + i = Ti [k] ; + j = Tj [k] ; + ASSERT (i == Ai [p]) ; + DEBUG1 ((" i "ID" j "ID" Ap[j] "ID" p "ID" Ap[j+1] "ID"\n", + i, j, Ap [j], p, Ap [j+1])) ; + ASSERT (Ap [j] <= p && p < Ap [j+1]) ; + } +#endif +#endif + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.h b/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_triplet.h @@ -0,0 +1,85 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_triplet_map_x +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], + const Int Tj [ ], + Int Ap [ ], + Int Ai [ ], + Int Rp [ ], + Int Rj [ ], + Int W [ ], + Int RowCount [ ] + , const double Tx [ ] + , double Ax [ ] + , double Rx [ ] +#ifdef COMPLEX + , const double Tz [ ] + , double Az [ ] + , double Rz [ ] +#endif + , Int Map [ ] + , Int Map2 [ ] +) ; + +GLOBAL Int UMF_triplet_map_nox +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], + const Int Tj [ ], + Int Ap [ ], + Int Ai [ ], + Int Rp [ ], + Int Rj [ ], + Int W [ ], + Int RowCount [ ] + , Int Map [ ] + , Int Map2 [ ] +) ; + +GLOBAL Int UMF_triplet_nomap_x +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], + const Int Tj [ ], + Int Ap [ ], + Int Ai [ ], + Int Rp [ ], + Int Rj [ ], + Int W [ ], + Int RowCount [ ] + , const double Tx [ ] + , double Ax [ ] + , double Rx [ ] +#ifdef COMPLEX + , const double Tz [ ] + , double Az [ ] + , double Rz [ ] +#endif +) ; + +GLOBAL Int UMF_triplet_nomap_nox +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], + const Int Tj [ ], + Int Ap [ ], + Int Ai [ ], + Int Rp [ ], + Int Rj [ ], + Int W [ ], + Int RowCount [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.c b/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.c @@ -0,0 +1,135 @@ +/* ========================================================================== */ +/* === UMF_tuple_lengths ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Determine the tuple list lengths, and the amount of memory required for */ +/* them. Return the amount of memory needed to store all the tuples. */ +/* This routine assumes that the tuple lists themselves are either already */ +/* deallocated, or will be shortly (so Row[ ].tlen and Col[ ].tlen are */ +/* overwritten) */ + +#include "umf_internal.h" + +GLOBAL Int UMF_tuple_lengths /* return memory usage */ +( + NumericType *Numeric, + WorkType *Work, + double *p_dusage /* output argument */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double dusage ; + Int e, nrows, ncols, nel, i, *Rows, *Cols, row, col, n_row, n_col, *E, + *Row_degree, *Row_tlen, *Col_degree, *Col_tlen, usage, n1 ; + Element *ep ; + Unit *p ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + E = Work->E ; + Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro only */ + Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro only */ + Row_tlen = Numeric->Uilen ; + Col_tlen = Numeric->Lilen ; + n_row = Work->n_row ; + n_col = Work->n_col ; + n1 = Work->n1 ; + nel = Work->nel ; + + DEBUG3 (("TUPLE_LENGTHS: n_row "ID" n_col "ID" nel "ID"\n", + n_row, n_col, nel)) ; + ASSERT (nel < Work->elen) ; + + /* tuple list lengths already initialized to zero */ + + /* ---------------------------------------------------------------------- */ + /* scan each element: count tuple list lengths (include element 0) */ + /* ---------------------------------------------------------------------- */ + + for (e = 1 ; e <= nel ; e++) /* for all elements, in any order */ + { + if (E [e]) + { +#ifndef NDEBUG + UMF_dump_element (Numeric, Work, e, FALSE) ; +#endif + p = Numeric->Memory + E [e] ; + GET_ELEMENT_PATTERN (ep, p, Cols, Rows, ncols) ; + nrows = ep->nrows ; + for (i = 0 ; i < nrows ; i++) + { + row = Rows [i] ; + ASSERT (row == EMPTY || (row >= n1 && row < n_row)) ; + if (row >= n1) + { + ASSERT (NON_PIVOTAL_ROW (row)) ; + Row_tlen [row] ++ ; + } + } + for (i = 0 ; i < ncols ; i++) + { + col = Cols [i] ; + ASSERT (col == EMPTY || (col >= n1 && col < n_col)) ; + if (col >= n1) + { + ASSERT (NON_PIVOTAL_COL (col)) ; + Col_tlen [col] ++ ; + } + } + } + } + + /* note: tuple lengths are now modified, but the tuple lists are not */ + /* updated to reflect that fact. */ + + /* ---------------------------------------------------------------------- */ + /* determine the required memory to hold all the tuple lists */ + /* ---------------------------------------------------------------------- */ + + DEBUG0 (("UMF_build_tuples_usage\n")) ; + + usage = 0 ; + dusage = 0 ; + + ASSERT (Col_tlen && Col_degree) ; + + for (col = n1 ; col < n_col ; col++) + { + if (NON_PIVOTAL_COL (col)) + { + usage += 1 + UNITS (Tuple, TUPLES (Col_tlen [col])) ; + dusage += 1 + DUNITS (Tuple, TUPLES (Col_tlen [col])) ; + DEBUG0 ((" col: "ID" tlen "ID" usage so far: "ID"\n", + col, Col_tlen [col], usage)) ; + } + } + + ASSERT (Row_tlen && Row_degree) ; + + for (row = n1 ; row < n_row ; row++) + { + if (NON_PIVOTAL_ROW (row)) + { + usage += 1 + UNITS (Tuple, TUPLES (Row_tlen [row])) ; + dusage += 1 + DUNITS (Tuple, TUPLES (Row_tlen [row])) ; + DEBUG0 ((" row: "ID" tlen "ID" usage so far: "ID"\n", + row, Row_tlen [row], usage)) ; + } + } + + DEBUG0 (("UMF_build_tuples_usage "ID" %g\n", usage, dusage)) ; + + *p_dusage = dusage ; + return (usage) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.h b/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_tuple_lengths.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_tuple_lengths +( + NumericType *Numeric, + WorkType *Work, + double *dusage +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.c b/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.c @@ -0,0 +1,226 @@ +/* ========================================================================== */ +/* === UMF_usolve =========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* solves Ux = b, where U is the upper triangular factor of a matrix. */ +/* B is overwritten with the solution X. */ +/* Returns the floating point operation count */ + +#include "umf_internal.h" + +GLOBAL double UMF_usolve +( + NumericType *Numeric, + Entry X [ ], /* b on input, solution x on output */ + Int Pattern [ ] /* a work array of size n */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry xk ; + Entry *xp, *D, *Uval ; + Int k, deg, j, *ip, col, *Upos, *Uilen, pos, + *Uip, n, ulen, up, newUchain, npiv, n1, *Ui ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + if (Numeric->n_row != Numeric->n_col) return (0.) ; + n = Numeric->n_row ; + npiv = Numeric->npiv ; + Upos = Numeric->Upos ; + Uilen = Numeric->Uilen ; + Uip = Numeric->Uip ; + D = Numeric->D ; + n1 = Numeric->n1 ; + +#ifndef NDEBUG + DEBUG4 (("Usolve start: npiv = "ID" n = "ID"\n", npiv, n)) ; + for (j = 0 ; j < n ; j++) + { + DEBUG4 (("Usolve start "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* singular case */ + /* ---------------------------------------------------------------------- */ + +#ifndef NO_DIVIDE_BY_ZERO + /* handle the singular part of D, up to just before the last pivot */ + for (k = n-1 ; k >= npiv ; k--) + { + /* This is an *** intentional *** divide-by-zero, to get Inf or Nan, + * as appropriate. It is not a bug. */ + ASSERT (IS_ZERO (D [k])) ; + xk = X [k] ; + /* X [k] = xk / D [k] ; */ + DIV (X [k], xk, D [k]) ; + } +#else + /* Do not divide by zero */ +#endif + + deg = Numeric->ulen ; + if (deg > 0) + { + /* :: make last pivot row of U (singular matrices only) :: */ + for (j = 0 ; j < deg ; j++) + { + DEBUG1 (("Last row of U: j="ID"\n", j)) ; + DEBUG1 (("Last row of U: Upattern[j]="ID"\n", + Numeric->Upattern [j]) ); + Pattern [j] = Numeric->Upattern [j] ; + } + } + + /* ---------------------------------------------------------------------- */ + /* nonsingletons */ + /* ---------------------------------------------------------------------- */ + + for (k = npiv-1 ; k >= n1 ; k--) + { + + /* ------------------------------------------------------------------ */ + /* use row k of U */ + /* ------------------------------------------------------------------ */ + + up = Uip [k] ; + ulen = Uilen [k] ; + newUchain = (up < 0) ; + if (newUchain) + { + up = -up ; + xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ; + } + else + { + xp = (Entry *) (Numeric->Memory + up) ; + } + + xk = X [k] ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" k "ID" col "ID" value", k, Pattern [j])) ; + EDEBUG4 (*xp) ; + DEBUG4 (("\n")) ; + /* xk -= X [Pattern [j]] * (*xp) ; */ + MULT_SUB (xk, X [Pattern [j]], *xp) ; + xp++ ; + } + +#ifndef NO_DIVIDE_BY_ZERO + /* Go ahead and divide by zero if D [k] is zero */ + /* X [k] = xk / D [k] ; */ + DIV (X [k], xk, D [k]) ; +#else + /* Do not divide by zero */ + if (IS_NONZERO (D [k])) + { + /* X [k] = xk / D [k] ; */ + DIV (X [k], xk, D [k]) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* make row k-1 of U in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + if (k == n1) break ; + + if (newUchain) + { + /* next row is a new Uchain */ + deg = ulen ; + ASSERT (IMPLIES (k == 0, deg == 0)) ; + DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ; + ip = (Int *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = *ip++ ; + DEBUG4 ((" k "ID" col "ID"\n", k-1, col)) ; + ASSERT (k <= col) ; + Pattern [j] = col ; + } + } + else + { + deg -= ulen ; + DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k, deg)) ; + ASSERT (deg >= 0) ; + pos = Upos [k] ; + if (pos != EMPTY) + { + /* add the pivot column */ + DEBUG4 (("k "ID" add pivot entry at pos "ID"\n", k, pos)) ; + ASSERT (pos >= 0 && pos <= deg) ; + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* singletons */ + /* ---------------------------------------------------------------------- */ + + for (k = n1 - 1 ; k >= 0 ; k--) + { + deg = Uilen [k] ; + xk = X [k] ; + DEBUG4 (("Singleton k "ID"\n", k)) ; + if (deg > 0) + { + up = Uip [k] ; + Ui = (Int *) (Numeric->Memory + up) ; + up += UNITS (Int, deg) ; + Uval = (Entry *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" k "ID" col "ID" value", k, Ui [j])) ; + EDEBUG4 (Uval [j]) ; + DEBUG4 (("\n")) ; + /* xk -= X [Ui [j]] * Uval [j] ; */ + ASSERT (Ui [j] >= 0 && Ui [j] < n) ; + MULT_SUB (xk, X [Ui [j]], Uval [j]) ; + } + } + +#ifndef NO_DIVIDE_BY_ZERO + /* Go ahead and divide by zero if D [k] is zero */ + /* X [k] = xk / D [k] ; */ + DIV (X [k], xk, D [k]) ; +#else + /* Do not divide by zero */ + if (IS_NONZERO (D [k])) + { + /* X [k] = xk / D [k] ; */ + DIV (X [k], xk, D [k]) ; + } +#endif + + } + +#ifndef NDEBUG + for (j = 0 ; j < n ; j++) + { + DEBUG4 (("Usolve done "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } + DEBUG4 (("Usolve done.\n")) ; +#endif + + return (DIV_FLOPS * ((double) n) + MULTSUB_FLOPS * ((double) Numeric->unz)); +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.h b/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_usolve.h @@ -0,0 +1,12 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL double UMF_usolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.c b/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.c @@ -0,0 +1,331 @@ +/* ========================================================================== */ +/* === UMF_utsolve ========================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* solves U'x = b or U.'x=b, where U is the upper triangular factor of a */ +/* matrix. B is overwritten with the solution X. */ +/* Returns the floating point operation count */ + +#include "umf_internal.h" + +GLOBAL double +#ifdef CONJUGATE_SOLVE +UMF_uhsolve /* solve U'x=b (complex conjugate transpose) */ +#else +UMF_utsolve /* solve U.'x=b (array transpose) */ +#endif +( + NumericType *Numeric, + Entry X [ ], /* b on input, solution x on output */ + Int Pattern [ ] /* a work array of size n */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry xk ; + Entry *xp, *D, *Uval ; + Int k, deg, j, *ip, col, *Upos, *Uilen, kstart, kend, up, + *Uip, n, uhead, ulen, pos, npiv, n1, *Ui ; + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + if (Numeric->n_row != Numeric->n_col) return (0.) ; + n = Numeric->n_row ; + npiv = Numeric->npiv ; + Upos = Numeric->Upos ; + Uilen = Numeric->Uilen ; + Uip = Numeric->Uip ; + D = Numeric->D ; + kend = 0 ; + n1 = Numeric->n1 ; + +#ifndef NDEBUG + DEBUG4 (("Utsolve start: npiv "ID" n "ID"\n", npiv, n)) ; + for (j = 0 ; j < n ; j++) + { + DEBUG4 (("Utsolve start "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* singletons */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + DEBUG4 (("Singleton k "ID"\n", k)) ; + +#ifndef NO_DIVIDE_BY_ZERO + /* Go ahead and divide by zero if D [k] is zero. */ +#ifdef CONJUGATE_SOLVE + /* xk = X [k] / conjugate (D [k]) ; */ + DIV_CONJ (xk, X [k], D [k]) ; +#else + /* xk = X [k] / D [k] ; */ + DIV (xk, X [k], D [k]) ; +#endif +#else + /* Do not divide by zero */ + if (IS_NONZERO (D [k])) + { +#ifdef CONJUGATE_SOLVE + /* xk = X [k] / conjugate (D [k]) ; */ + DIV_CONJ (xk, X [k], D [k]) ; +#else + /* xk = X [k] / D [k] ; */ + DIV (xk, X [k], D [k]) ; +#endif + } +#endif + + X [k] = xk ; + deg = Uilen [k] ; + if (deg > 0 && IS_NONZERO (xk)) + { + up = Uip [k] ; + Ui = (Int *) (Numeric->Memory + up) ; + up += UNITS (Int, deg) ; + Uval = (Entry *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" k "ID" col "ID" value", k, Ui [j])) ; + EDEBUG4 (Uval [j]) ; + DEBUG4 (("\n")) ; +#ifdef CONJUGATE_SOLVE + /* X [Ui [j]] -= xk * conjugate (Uval [j]) ; */ + MULT_SUB_CONJ (X [Ui [j]], xk, Uval [j]) ; +#else + /* X [Ui [j]] -= xk * Uval [j] ; */ + MULT_SUB (X [Ui [j]], xk, Uval [j]) ; +#endif + } + } + } + + /* ---------------------------------------------------------------------- */ + /* nonsingletons */ + /* ---------------------------------------------------------------------- */ + + for (kstart = n1 ; kstart < npiv ; kstart = kend + 1) + { + + /* ------------------------------------------------------------------ */ + /* find the end of this Uchain */ + /* ------------------------------------------------------------------ */ + + DEBUG4 (("kstart "ID" kend "ID"\n", kstart, kend)) ; + /* for (kend = kstart ; kend < npiv && Uip [kend+1] > 0 ; kend++) ; */ + kend = kstart ; + while (kend < npiv && Uip [kend+1] > 0) + { + kend++ ; + } + + /* ------------------------------------------------------------------ */ + /* scan the whole Uchain to find the pattern of the first row of U */ + /* ------------------------------------------------------------------ */ + + k = kend+1 ; + DEBUG4 (("\nKend "ID" K "ID"\n", kend, k)) ; + + /* ------------------------------------------------------------------ */ + /* start with last row in Uchain of U in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + if (k == npiv) + { + deg = Numeric->ulen ; + if (deg > 0) + { + /* :: make last pivot row of U (singular matrices only) :: */ + for (j = 0 ; j < deg ; j++) + { + Pattern [j] = Numeric->Upattern [j] ; + } + } + } + else + { + ASSERT (k >= 0 && k < npiv) ; + up = -Uip [k] ; + ASSERT (up > 0) ; + deg = Uilen [k] ; + DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ; + ip = (Int *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = *ip++ ; + DEBUG4 ((" k "ID" col "ID"\n", k-1, col)) ; + ASSERT (k <= col) ; + Pattern [j] = col ; + } + } + + /* empty the stack at the bottom of Pattern */ + uhead = n ; + + for (k = kend ; k > kstart ; k--) + { + /* Pattern [0..deg-1] is the pattern of row k of U */ + + /* -------------------------------------------------------------- */ + /* make row k-1 of U in Pattern [0..deg-1] */ + /* -------------------------------------------------------------- */ + + ASSERT (k >= 0 && k < npiv) ; + ulen = Uilen [k] ; + /* delete, and push on the stack */ + for (j = 0 ; j < ulen ; j++) + { + ASSERT (uhead >= deg) ; + Pattern [--uhead] = Pattern [--deg] ; + } + DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k, deg)) ; + ASSERT (deg >= 0) ; + + pos = Upos [k] ; + if (pos != EMPTY) + { + /* add the pivot column */ + DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ; + ASSERT (pos >= 0 && pos <= deg) ; + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + } + + /* Pattern [0..deg-1] is now the pattern of the first row in Uchain */ + + /* ------------------------------------------------------------------ */ + /* solve using this Uchain, in reverse order */ + /* ------------------------------------------------------------------ */ + + DEBUG4 (("Unwinding Uchain\n")) ; + for (k = kstart ; k <= kend ; k++) + { + + /* -------------------------------------------------------------- */ + /* construct row k */ + /* -------------------------------------------------------------- */ + + ASSERT (k >= 0 && k < npiv) ; + pos = Upos [k] ; + if (pos != EMPTY) + { + /* remove the pivot column */ + DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ; + ASSERT (k > kstart) ; + ASSERT (pos >= 0 && pos < deg) ; + ASSERT (Pattern [pos] == k) ; + Pattern [pos] = Pattern [--deg] ; + } + + up = Uip [k] ; + ulen = Uilen [k] ; + if (k > kstart) + { + /* concatenate the deleted pattern; pop from the stack */ + for (j = 0 ; j < ulen ; j++) + { + ASSERT (deg <= uhead && uhead < n) ; + Pattern [deg++] = Pattern [uhead++] ; + } + DEBUG4 (("middle of chain, row of U "ID" deg "ID"\n", k, deg)) ; + ASSERT (deg >= 0) ; + } + + /* -------------------------------------------------------------- */ + /* use row k of U */ + /* -------------------------------------------------------------- */ + +#ifndef NO_DIVIDE_BY_ZERO + /* Go ahead and divide by zero if D [k] is zero. */ +#ifdef CONJUGATE_SOLVE + /* xk = X [k] / conjugate (D [k]) ; */ + DIV_CONJ (xk, X [k], D [k]) ; +#else + /* xk = X [k] / D [k] ; */ + DIV (xk, X [k], D [k]) ; +#endif +#else + /* Do not divide by zero */ + if (IS_NONZERO (D [k])) + { +#ifdef CONJUGATE_SOLVE + /* xk = X [k] / conjugate (D [k]) ; */ + DIV_CONJ (xk, X [k], D [k]) ; +#else + /* xk = X [k] / D [k] ; */ + DIV (xk, X [k], D [k]) ; +#endif + } +#endif + + X [k] = xk ; + if (IS_NONZERO (xk)) + { + if (k == kstart) + { + up = -up ; + xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ; + } + else + { + xp = (Entry *) (Numeric->Memory + up) ; + } + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" k "ID" col "ID" value", k, Pattern [j])) ; + EDEBUG4 (*xp) ; + DEBUG4 (("\n")) ; +#ifdef CONJUGATE_SOLVE + /* X [Pattern [j]] -= xk * conjugate (*xp) ; */ + MULT_SUB_CONJ (X [Pattern [j]], xk, *xp) ; +#else + /* X [Pattern [j]] -= xk * (*xp) ; */ + MULT_SUB (X [Pattern [j]], xk, *xp) ; +#endif + xp++ ; + } + } + } + ASSERT (uhead == n) ; + } + +#ifndef NO_DIVIDE_BY_ZERO + for (k = npiv ; k < n ; k++) + { + /* This is an *** intentional *** divide-by-zero, to get Inf or Nan, + * as appropriate. It is not a bug. */ + ASSERT (IS_ZERO (D [k])) ; + /* For conjugate solve, D [k] == conjugate (D [k]), in this case */ + /* xk = X [k] / D [k] ; */ + DIV (xk, X [k], D [k]) ; + X [k] = xk ; + } +#endif + +#ifndef NDEBUG + for (j = 0 ; j < n ; j++) + { + DEBUG4 (("Utsolve done "ID": ", j)) ; + EDEBUG4 (X [j]) ; + DEBUG4 (("\n")) ; + } + DEBUG4 (("Utsolve done.\n")) ; +#endif + + return (DIV_FLOPS * ((double) n) + MULTSUB_FLOPS * ((double) Numeric->unz)); +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.h b/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_utsolve.h @@ -0,0 +1,20 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL double UMF_utsolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; + + +GLOBAL double UMF_uhsolve +( + NumericType *Numeric, + Entry X [ ], + Int Pattern [ ] +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.c @@ -0,0 +1,46 @@ +/* ========================================================================== */ +/* === UMF_valid_numeric ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* Returns TRUE if the Numeric object is valid, FALSE otherwise. */ +/* Does not check everything. UMFPACK_report_numeric checks more. */ + +#include "umf_internal.h" + +GLOBAL Int UMF_valid_numeric +( + NumericType *Numeric +) +{ + /* This routine does not check the contents of the individual arrays, so */ + /* it can miss some errors. All it checks for is the presence of the */ + /* arrays, and the Numeric "valid" entry. */ + + if (!Numeric) + { + return (FALSE) ; + } + + if (Numeric->valid != NUMERIC_VALID) + { + /* Numeric does not point to a NumericType object */ + return (FALSE) ; + } + + if (Numeric->n_row <= 0 || Numeric->n_col <= 0 || !Numeric->D || + !Numeric->Rperm || !Numeric->Cperm || + !Numeric->Lpos || !Numeric->Upos || + !Numeric->Lilen || !Numeric->Uilen || !Numeric->Lip || !Numeric->Uip || + !Numeric->Memory || (Numeric->ulen > 0 && !Numeric->Upattern)) + { + return (FALSE) ; + } + + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.h b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_numeric.h @@ -0,0 +1,10 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_valid_numeric +( + NumericType *Numeric +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.c @@ -0,0 +1,47 @@ +/* ========================================================================== */ +/* === UMF_valid_symbolic =================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +#include "umf_internal.h" + +/* Returns TRUE if the Symbolic object is valid, FALSE otherwise. */ +/* The UMFPACK_report_symbolic routine does a more thorough check. */ + +GLOBAL Int UMF_valid_symbolic +( + SymbolicType *Symbolic +) +{ + /* This routine does not check the contents of the individual arrays, so */ + /* it can miss some errors. All it checks for is the presence of the */ + /* arrays, and the Symbolic "valid" entry. */ + + if (!Symbolic) + { + return (FALSE) ; + } + + if (Symbolic->valid != SYMBOLIC_VALID) + { + /* Symbolic does not point to a SymbolicType object */ + return (FALSE) ; + } + + if (!Symbolic->Cperm_init || !Symbolic->Rperm_init || + !Symbolic->Front_npivcol || !Symbolic->Front_1strow || + !Symbolic->Front_leftmostdesc || + !Symbolic->Front_parent || !Symbolic->Chain_start || + !Symbolic->Chain_maxrows || !Symbolic->Chain_maxcols || + Symbolic->n_row <= 0 || Symbolic->n_col <= 0) + { + return (FALSE) ; + } + + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.h b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_valid_symbolic.h @@ -0,0 +1,10 @@ +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +GLOBAL Int UMF_valid_symbolic +( + SymbolicType *Symbolic +) ; diff --git a/liboctave/UMFPACK/UMFPACK/Source/umf_version.h b/liboctave/UMFPACK/UMFPACK/Source/umf_version.h new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umf_version.h @@ -0,0 +1,1001 @@ +/* ========================================================================== */ +/* === umf_version.h ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + Define routine names, depending on version being compiled. + + DINT: double precision, int's as integers + DLONG: double precision, long's as integers + ZLONG: complex double precision, long's as integers + ZINT: complex double precision, int's as integers +*/ + +/* Set DINT as the default, if nothing is defined */ +#if !defined (DLONG) && !defined (DINT) && !defined (ZLONG) && !defined (ZINT) +#define DINT +#endif + +/* Determine if this is a real or complex version */ +#if defined (ZLONG) || defined (ZINT) +#define COMPLEX +#endif + +/* -------------------------------------------------------------------------- */ +/* integer type (Int is int or long) now defined in amd_internal.h */ +/* -------------------------------------------------------------------------- */ + +#if defined (DLONG) || defined (ZLONG) +#define LONG_INTEGER +#endif + +/* -------------------------------------------------------------------------- */ +/* Numerical relop macros for correctly handling the NaN case */ +/* -------------------------------------------------------------------------- */ + +/* +SCALAR_IS_NAN(x): + True if x is NaN. False otherwise. The commonly-existing isnan(x) + function could be used, but it's not in Kernighan & Ritchie 2nd edition + (ANSI C). It may appear in , but I'm not certain about + portability. The expression x != x is true if and only if x is NaN, + according to the IEEE 754 floating-point standard. + +SCALAR_IS_ZERO(x): + True if x is zero. False if x is nonzero, NaN, or +/- Inf. + This is (x == 0) if the compiler is IEEE 754 compliant. + +SCALAR_IS_NONZERO(x): + True if x is nonzero, NaN, or +/- Inf. False if x zero. + This is (x != 0) if the compiler is IEEE 754 compliant. + +SCALAR_IS_LTZERO(x): + True if x is < zero or -Inf. False if x is >= 0, NaN, or +Inf. + This is (x < 0) if the compiler is IEEE 754 compliant. +*/ + +#if defined (MATHWORKS) + +/* The MathWorks has their own macros in util.h that handle NaN's properly. */ +#define SCALAR_IS_NAN(x) (utIsNaN (x)) +#define SCALAR_IS_ZERO(x) (utEQZero (x)) +#define SCALAR_IS_NONZERO(x) (utNEZero (x)) +#define SCALAR_IS_LTZERO(x) (utLTZero (x)) + +#elif defined (UMF_WINDOWS) + +/* Yes, this is exceedingly ugly. Blame Microsoft, which hopelessly */ +/* violates the IEEE 754 floating-point standard in a bizarre way. */ +/* If you're using an IEEE 754-compliant compiler, then x != x is true */ +/* iff x is NaN. For Microsoft, (x < x) is true iff x is NaN. */ +/* So either way, this macro safely detects a NaN. */ +#define SCALAR_IS_NAN(x) (((x) != (x)) || (((x) < (x)))) +#define SCALAR_IS_ZERO(x) (((x) == 0.) && !SCALAR_IS_NAN(x)) +#define SCALAR_IS_NONZERO(x) (((x) != 0.) || SCALAR_IS_NAN(x)) +#define SCALAR_IS_LTZERO(x) (((x) < 0.) && !SCALAR_IS_NAN(x)) + +#else + +/* These all work properly, according to the IEEE 754 standard ... except on */ +/* a PC with windows. Works fine in Linux on the same PC... */ +#define SCALAR_IS_NAN(x) ((x) != (x)) +#define SCALAR_IS_ZERO(x) ((x) == 0.) +#define SCALAR_IS_NONZERO(x) ((x) != 0.) +#define SCALAR_IS_LTZERO(x) ((x) < 0.) + +#endif + +/* scalar absolute value macro. If x is NaN, the result is NaN: */ +#define SCALAR_ABS(x) ((SCALAR_IS_LTZERO (x)) ? -(x) : (x)) + +/* true if an integer (stored in double x) would overflow (or if x is NaN) */ +#define INT_OVERFLOW(x) ((!((x) * (1.0+1e-8) <= (double) Int_MAX)) \ + || SCALAR_IS_NAN (x)) + +/* print a scalar (avoid printing "-0" for negative zero). */ +#define PRINT_SCALAR(a) \ +{ \ + if (SCALAR_IS_NONZERO (a)) \ + { \ + PRINTF ((" (%g)", (a))) ; \ + } \ + else \ + { \ + PRINTF ((" (0)")) ; \ + } \ +} + +/* -------------------------------------------------------------------------- */ +/* Real floating-point arithmetic */ +/* -------------------------------------------------------------------------- */ + +#ifndef COMPLEX + +#define Entry double + +#define SPLIT(s) (1) +#define REAL_COMPONENT(c) (c) +#define IMAG_COMPONENT(c) (0.) +#define ASSIGN(c,s1,s2,p,split) { (c) = (s1)[p] ; } +#define CLEAR(c) { (c) = 0. ; } +#define CLEAR_AND_INCREMENT(p) { *p++ = 0. ; } +#define IS_NAN(a) SCALAR_IS_NAN (a) +#define IS_ZERO(a) SCALAR_IS_ZERO (a) +#define IS_NONZERO(a) SCALAR_IS_NONZERO (a) +#define SCALE_DIV(c,s) { (c) /= (s) ; } +#define SCALE(c,s) { (c) *= (s) ; } +#define ASSEMBLE(c,a) { (c) += (a) ; } +#define ASSEMBLE_AND_INCREMENT(c,p) { (c) += *p++ ; } +#define DECREMENT(c,a) { (c) -= (a) ; } +#define MULT(c,a,b) { (c) = (a) * (b) ; } +#define MULT_CONJ(c,a,b) { (c) = (a) * (b) ; } +#define MULT_SUB(c,a,b) { (c) -= (a) * (b) ; } +#define MULT_SUB_CONJ(c,a,b) { (c) -= (a) * (b) ; } +#define DIV(c,a,b) { (c) = (a) / (b) ; } +#define RECIPROCAL(c) { (c) = 1.0 / (c) ; } +#define DIV_CONJ(c,a,b) { (c) = (a) / (b) ; } +#define APPROX_ABS(s,a) { (s) = SCALAR_ABS (a) ; } +#define ABS(s,a) { (s) = SCALAR_ABS (a) ; } +#define PRINT_ENTRY(a) PRINT_SCALAR (a) + +/* for flop counts */ +#define MULTSUB_FLOPS 2. /* c -= a*b */ +#define DIV_FLOPS 1. /* c = a/b */ +#define ABS_FLOPS 0. /* c = abs (a) */ +#define ASSEMBLE_FLOPS 1. /* c += a */ +#define DECREMENT_FLOPS 1. /* c -= a */ +#define MULT_FLOPS 1. /* c = a*b */ +#define SCALE_FLOPS 1. /* c = a/s */ + +#else + +/* -------------------------------------------------------------------------- */ +/* Complex floating-point arithmetic */ +/* -------------------------------------------------------------------------- */ + +/* + Note: An alternative to this DoubleComplex type would be to use a + struct { double r ; double i ; }. The problem with that method + (used by the Sun Performance Library, for example) is that ANSI C provides + no guarantee about the layout of a struct. It is possible that the sizeof + the struct above would be greater than 2 * sizeof (double). This would + mean that the complex BLAS could not be used. The method used here avoids + that possibility. ANSI C *does* guarantee that an array of structs has + the same size as n times the size of one struct. + + The ANSI C99 version of the C language includes a "double _Complex" type. + It should be possible in that case to do the following: + + #define Entry double _Complex + + and remove the DoubleComplex struct. The macros, below, could then be + replaced with instrinsic operators. Note that the #define Real and + #define Imag should also be removed (they only appear in this file). + + For the MULT, MULT_SUB, MULT_SUB_CONJ, and MULT_CONJ macros, + the output argument c cannot be the same as any input argument. + +*/ + +typedef struct +{ + double component [2] ; /* real and imaginary parts */ + +} DoubleComplex ; + +#define Entry DoubleComplex +#define Real component [0] +#define Imag component [1] + +/* for flop counts */ +#define MULTSUB_FLOPS 8. /* c -= a*b */ +#define DIV_FLOPS 9. /* c = a/b */ +#define ABS_FLOPS 6. /* c = abs (a), count sqrt as one flop */ +#define ASSEMBLE_FLOPS 2. /* c += a */ +#define DECREMENT_FLOPS 2. /* c -= a */ +#define MULT_FLOPS 6. /* c = a*b */ +#define SCALE_FLOPS 2. /* c = a/s or c = a*s */ + +/* -------------------------------------------------------------------------- */ + +/* real part of c */ +#define REAL_COMPONENT(c) ((c).Real) + +/* -------------------------------------------------------------------------- */ + +/* imag part of c */ +#define IMAG_COMPONENT(c) ((c).Imag) + +/* -------------------------------------------------------------------------- */ + +/* Return TRUE if a complex number is in split form, FALSE if in packed form */ +#define SPLIT(sz) ((sz) != (double *) NULL) + +/* -------------------------------------------------------------------------- */ + +/* c = (s1) + (s2)*i, if s2 is null, then X is in "packed" format (compatible + * with Entry and ANSI C99 double _Complex type). */ +#define ASSIGN(c,s1,s2,p,split) \ +{ \ + if (split) \ + { \ + (c).Real = (s1)[p] ; \ + (c).Imag = (s2)[p] ; \ + } \ + else \ + { \ + (c) = ((Entry *)(s1))[p] ; \ + } \ +} + +/* -------------------------------------------------------------------------- */ + +/* c = 0 */ +#define CLEAR(c) \ +{ \ + (c).Real = 0. ; \ + (c).Imag = 0. ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* *p++ = 0 */ +#define CLEAR_AND_INCREMENT(p) \ +{ \ + p->Real = 0. ; \ + p->Imag = 0. ; \ + p++ ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* True if a == 0 */ +#define IS_ZERO(a) \ + (SCALAR_IS_ZERO ((a).Real) && SCALAR_IS_ZERO ((a).Imag)) + +/* -------------------------------------------------------------------------- */ + +/* True if a is NaN */ +#define IS_NAN(a) \ + (SCALAR_IS_NAN ((a).Real) || SCALAR_IS_NAN ((a).Imag)) + +/* -------------------------------------------------------------------------- */ + +/* True if a != 0 */ +#define IS_NONZERO(a) \ + (SCALAR_IS_NONZERO ((a).Real) || SCALAR_IS_NONZERO ((a).Imag)) + +/* -------------------------------------------------------------------------- */ + +/* c /= s */ +#define SCALE_DIV(c,s) \ +{ \ + (c).Real /= (s) ; \ + (c).Imag /= (s) ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c *= s */ +#define SCALE(c,s) \ +{ \ + (c).Real *= (s) ; \ + (c).Imag *= (s) ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c += a */ +#define ASSEMBLE(c,a) \ +{ \ + (c).Real += (a).Real ; \ + (c).Imag += (a).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c += *p++ */ +#define ASSEMBLE_AND_INCREMENT(c,p) \ +{ \ + (c).Real += p->Real ; \ + (c).Imag += p->Imag ; \ + p++ ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c -= a */ +#define DECREMENT(c,a) \ +{ \ + (c).Real -= (a).Real ; \ + (c).Imag -= (a).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c = a*b, assert because c cannot be the same as a or b */ +#define MULT(c,a,b) \ +{ \ + ASSERT (&(c) != &(a) && &(c) != &(b)) ; \ + (c).Real = (a).Real * (b).Real - (a).Imag * (b).Imag ; \ + (c).Imag = (a).Imag * (b).Real + (a).Real * (b).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c = a*conjugate(b), assert because c cannot be the same as a or b */ +#define MULT_CONJ(c,a,b) \ +{ \ + ASSERT (&(c) != &(a) && &(c) != &(b)) ; \ + (c).Real = (a).Real * (b).Real + (a).Imag * (b).Imag ; \ + (c).Imag = (a).Imag * (b).Real - (a).Real * (b).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c -= a*b, assert because c cannot be the same as a or b */ +#define MULT_SUB(c,a,b) \ +{ \ + ASSERT (&(c) != &(a) && &(c) != &(b)) ; \ + (c).Real -= (a).Real * (b).Real - (a).Imag * (b).Imag ; \ + (c).Imag -= (a).Imag * (b).Real + (a).Real * (b).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c -= a*conjugate(b), assert because c cannot be the same as a or b */ +#define MULT_SUB_CONJ(c,a,b) \ +{ \ + ASSERT (&(c) != &(a) && &(c) != &(b)) ; \ + (c).Real -= (a).Real * (b).Real + (a).Imag * (b).Imag ; \ + (c).Imag -= (a).Imag * (b).Real - (a).Real * (b).Imag ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* c = a/b, be careful to avoid underflow and overflow */ +#ifdef MATHWORKS +#define DIV(c,a,b) \ +{ \ + (void) utDivideComplex ((a).Real, (a).Imag, (b).Real, (b).Imag, \ + &((c).Real), &((c).Imag)) ; \ +} +#else +/* This uses ACM Algo 116, by R. L. Smith, 1962. */ +/* c can be the same variable as a or b. */ +/* Ignore NaN case for double relop br>=bi. */ +#define DIV(c,a,b) \ +{ \ + double r, den, ar, ai, br, bi ; \ + br = (b).Real ; \ + bi = (b).Imag ; \ + ar = (a).Real ; \ + ai = (a).Imag ; \ + if (SCALAR_ABS (br) >= SCALAR_ABS (bi)) \ + { \ + r = bi / br ; \ + den = br + r * bi ; \ + (c).Real = (ar + ai * r) / den ; \ + (c).Imag = (ai - ar * r) / den ; \ + } \ + else \ + { \ + r = br / bi ; \ + den = r * br + bi ; \ + (c).Real = (ar * r + ai) / den ; \ + (c).Imag = (ai * r - ar) / den ; \ + } \ +} +#endif + +/* -------------------------------------------------------------------------- */ + +/* c = 1/c, be careful to avoid underflow and overflow */ +/* Not used if MATHWORKS is defined. */ +/* This uses ACM Algo 116, by R. L. Smith, 1962. */ +/* Ignore NaN case for double relop cr>=ci. */ +#define RECIPROCAL(c) \ +{ \ + double r, den, cr, ci ; \ + cr = (c).Real ; \ + ci = (c).Imag ; \ + if (SCALAR_ABS (cr) >= SCALAR_ABS (ci)) \ + { \ + r = ci / cr ; \ + den = cr + r * ci ; \ + (c).Real = 1.0 / den ; \ + (c).Imag = - r / den ; \ + } \ + else \ + { \ + r = cr / ci ; \ + den = r * cr + ci ; \ + (c).Real = r / den ; \ + (c).Imag = - 1.0 / den ; \ + } \ +} + + +/* -------------------------------------------------------------------------- */ + +/* c = a/conjugate(b), be careful to avoid underflow and overflow */ +#ifdef MATHWORKS +#define DIV_CONJ(c,a,b) \ +{ \ + (void) utDivideComplex ((a).Real, (a).Imag, (b).Real, (-(b).Imag), \ + &((c).Real), &((c).Imag)) ; \ +} +#else +/* This uses ACM Algo 116, by R. L. Smith, 1962. */ +/* c can be the same variable as a or b. */ +/* Ignore NaN case for double relop br>=bi. */ +#define DIV_CONJ(c,a,b) \ +{ \ + double r, den, ar, ai, br, bi ; \ + br = (b).Real ; \ + bi = (b).Imag ; \ + ar = (a).Real ; \ + ai = (a).Imag ; \ + if (SCALAR_ABS (br) >= SCALAR_ABS (bi)) \ + { \ + r = (-bi) / br ; \ + den = br - r * bi ; \ + (c).Real = (ar + ai * r) / den ; \ + (c).Imag = (ai - ar * r) / den ; \ + } \ + else \ + { \ + r = br / (-bi) ; \ + den = r * br - bi; \ + (c).Real = (ar * r + ai) / den ; \ + (c).Imag = (ai * r - ar) / den ; \ + } \ +} +#endif + +/* -------------------------------------------------------------------------- */ + +/* approximate absolute value, s = |r|+|i| */ +#define APPROX_ABS(s,a) \ +{ \ + (s) = SCALAR_ABS ((a).Real) + SCALAR_ABS ((a).Imag) ; \ +} + +/* -------------------------------------------------------------------------- */ + +/* exact absolute value, s = sqrt (a.real^2 + amag^2) */ +#ifdef MATHWORKS +#define ABS(s,a) \ +{ \ + (s) = utFdlibm_hypot ((a).Real, (a).Imag) ; \ +} +#else +/* Ignore NaN case for the double relops ar>=ai and ar+ai==ar. */ +#define ABS(s,a) \ +{ \ + double r, ar, ai ; \ + ar = SCALAR_ABS ((a).Real) ; \ + ai = SCALAR_ABS ((a).Imag) ; \ + if (ar >= ai) \ + { \ + if (ar + ai == ar) \ + { \ + (s) = ar ; \ + } \ + else \ + { \ + r = ai / ar ; \ + (s) = ar * sqrt (1.0 + r*r) ; \ + } \ + } \ + else \ + { \ + if (ai + ar == ai) \ + { \ + (s) = ai ; \ + } \ + else \ + { \ + r = ar / ai ; \ + (s) = ai * sqrt (1.0 + r*r) ; \ + } \ + } \ +} +#endif + +/* -------------------------------------------------------------------------- */ + +/* print an entry (avoid printing "-0" for negative zero). */ +#define PRINT_ENTRY(a) \ +{ \ + if (SCALAR_IS_NONZERO ((a).Real)) \ + { \ + PRINTF ((" (%g", (a).Real)) ; \ + } \ + else \ + { \ + PRINTF ((" (0")) ; \ + } \ + if (SCALAR_IS_LTZERO ((a).Imag)) \ + { \ + PRINTF ((" - %gi)", -(a).Imag)) ; \ + } \ + else if (SCALAR_IS_ZERO ((a).Imag)) \ + { \ + PRINTF ((" + 0i)")) ; \ + } \ + else \ + { \ + PRINTF ((" + %gi)", (a).Imag)) ; \ + } \ +} + +/* -------------------------------------------------------------------------- */ + +#endif /* #ifndef COMPLEX */ + +/* -------------------------------------------------------------------------- */ +/* Double precision, with int's as integers */ +/* -------------------------------------------------------------------------- */ + +#ifdef DINT + +#define UMF_analyze umf_i_analyze +#define UMF_apply_order umf_i_apply_order +#define UMF_assemble umfdi_assemble +#define UMF_assemble_fixq umfdi_assemble_fixq +#define UMF_blas3_update umfdi_blas3_update +#define UMF_build_tuples umfdi_build_tuples +#define UMF_build_tuples_usage umfdi_build_tuples_usage +#define UMF_colamd umf_i_colamd +#define UMF_colamd_set_defaults umf_i_colamd_set_defaults +#define UMF_create_element umfdi_create_element +#define UMF_extend_front umfdi_extend_front +#define UMF_free umf_i_free +#define UMF_fsize umf_i_fsize +#define UMF_garbage_collection umfdi_garbage_collection +#define UMF_get_memory umfdi_get_memory +#define UMF_grow_front umfdi_grow_front +#define UMF_init_front umfdi_init_front +#define UMF_is_permutation umf_i_is_permutation +#define UMF_kernel umfdi_kernel +#define UMF_kernel_init umfdi_kernel_init +#define UMF_kernel_init_usage umfdi_kernel_init_usage +#define UMF_kernel_wrapup umfdi_kernel_wrapup +#define UMF_local_search umfdi_local_search +#define UMF_lsolve umfdi_lsolve +#define UMF_ltsolve umfdi_ltsolve +#define UMF_lhsolve umfdi_lhsolve +#define UMF_malloc umf_i_malloc +#define UMF_mem_alloc_element umfdi_mem_alloc_element +#define UMF_mem_alloc_head_block umfdi_mem_alloc_head_block +#define UMF_mem_alloc_tail_block umfdi_mem_alloc_tail_block +#define UMF_mem_free_tail_block umfdi_mem_free_tail_block +#define UMF_mem_init_memoryspace umfdi_mem_init_memoryspace +#define UMF_realloc umf_i_realloc +#define UMF_report_perm umf_i_report_perm +#define UMF_report_vector umfdi_report_vector +#define UMF_row_search umfdi_row_search +#define UMF_scale umfdi_scale +#define UMF_scale_column umfdi_scale_column +#define UMF_set_stats umf_i_set_stats +#define UMF_singletons umf_i_singletons +#define UMF_solve umfdi_solve +#define UMF_start_front umfdi_start_front +#define UMF_store_lu umfdi_store_lu +#define UMF_store_lu_drop umfdi_store_lu_drop +#define UMF_symbolic_usage umfdi_symbolic_usage +#define UMF_transpose umfdi_transpose +#define UMF_tuple_lengths umfdi_tuple_lengths +#define UMF_usolve umfdi_usolve +#define UMF_utsolve umfdi_utsolve +#define UMF_uhsolve umfdi_uhsolve +#define UMF_valid_numeric umfdi_valid_numeric +#define UMF_valid_symbolic umfdi_valid_symbolic +#define UMF_triplet_map_x umfdi_triplet_map_x +#define UMF_triplet_map_nox umfdi_triplet_map_nox +#define UMF_triplet_nomap_x umfdi_triplet_nomap_x +#define UMF_triplet_nomap_nox umfdi_triplet_nomap_nox +#define UMF_2by2 umfdi_2by2 + +#define UMFPACK_col_to_triplet umfpack_di_col_to_triplet +#define UMFPACK_defaults umfpack_di_defaults +#define UMFPACK_free_numeric umfpack_di_free_numeric +#define UMFPACK_free_symbolic umfpack_di_free_symbolic +#define UMFPACK_get_lunz umfpack_di_get_lunz +#define UMFPACK_get_numeric umfpack_di_get_numeric +#define UMFPACK_get_symbolic umfpack_di_get_symbolic +#define UMFPACK_get_determinant umfpack_di_get_determinant +#define UMFPACK_numeric umfpack_di_numeric +#define UMFPACK_qsymbolic umfpack_di_qsymbolic +#define UMFPACK_report_control umfpack_di_report_control +#define UMFPACK_report_info umfpack_di_report_info +#define UMFPACK_report_matrix umfpack_di_report_matrix +#define UMFPACK_report_numeric umfpack_di_report_numeric +#define UMFPACK_report_perm umfpack_di_report_perm +#define UMFPACK_report_status umfpack_di_report_status +#define UMFPACK_report_symbolic umfpack_di_report_symbolic +#define UMFPACK_report_triplet umfpack_di_report_triplet +#define UMFPACK_report_vector umfpack_di_report_vector +#define UMFPACK_save_numeric umfpack_di_save_numeric +#define UMFPACK_save_symbolic umfpack_di_save_symbolic +#define UMFPACK_load_numeric umfpack_di_load_numeric +#define UMFPACK_load_symbolic umfpack_di_load_symbolic +#define UMFPACK_scale umfpack_di_scale +#define UMFPACK_solve umfpack_di_solve +#define UMFPACK_symbolic umfpack_di_symbolic +#define UMFPACK_transpose umfpack_di_transpose +#define UMFPACK_triplet_to_col umfpack_di_triplet_to_col +#define UMFPACK_wsolve umfpack_di_wsolve + +/* for debugging only: */ +#define UMF_malloc_count umf_i_malloc_count +#define UMF_debug umfdi_debug +#define UMF_allocfail umfdi_allocfail +#define UMF_gprob umfdi_gprob +#define UMF_dump_dense umfdi_dump_dense +#define UMF_dump_element umfdi_dump_element +#define UMF_dump_rowcol umfdi_dump_rowcol +#define UMF_dump_matrix umfdi_dump_matrix +#define UMF_dump_current_front umfdi_dump_current_front +#define UMF_dump_lu umfdi_dump_lu +#define UMF_dump_memory umfdi_dump_memory +#define UMF_dump_packed_memory umfdi_dump_packed_memory +#define UMF_dump_col_matrix umfdi_dump_col_matrix +#define UMF_dump_chain umfdi_dump_chain +#define UMF_dump_start umfdi_dump_start +#define UMF_dump_rowmerge umfdi_dump_rowmerge +#define UMF_dump_diagonal_map umfdi_dump_diagonal_map + +#endif + +/* -------------------------------------------------------------------------- */ +/* Double precision, with long's as integers */ +/* -------------------------------------------------------------------------- */ + +#ifdef DLONG + +#define UMF_analyze umf_l_analyze +#define UMF_apply_order umf_l_apply_order +#define UMF_assemble umfdl_assemble +#define UMF_assemble_fixq umfdl_assemble_fixq +#define UMF_blas3_update umfdl_blas3_update +#define UMF_build_tuples umfdl_build_tuples +#define UMF_build_tuples_usage umfdl_build_tuples_usage +#define UMF_colamd umf_l_colamd +#define UMF_colamd_set_defaults umf_l_colamd_set_defaults +#define UMF_create_element umfdl_create_element +#define UMF_extend_front umfdl_extend_front +#define UMF_free umf_l_free +#define UMF_fsize umf_l_fsize +#define UMF_garbage_collection umfdl_garbage_collection +#define UMF_get_memory umfdl_get_memory +#define UMF_grow_front umfdl_grow_front +#define UMF_init_front umfdl_init_front +#define UMF_is_permutation umf_l_is_permutation +#define UMF_kernel umfdl_kernel +#define UMF_kernel_init umfdl_kernel_init +#define UMF_kernel_init_usage umfdl_kernel_init_usage +#define UMF_kernel_wrapup umfdl_kernel_wrapup +#define UMF_local_search umfdl_local_search +#define UMF_lsolve umfdl_lsolve +#define UMF_ltsolve umfdl_ltsolve +#define UMF_lhsolve umfdl_lhsolve +#define UMF_malloc umf_l_malloc +#define UMF_mem_alloc_element umfdl_mem_alloc_element +#define UMF_mem_alloc_head_block umfdl_mem_alloc_head_block +#define UMF_mem_alloc_tail_block umfdl_mem_alloc_tail_block +#define UMF_mem_free_tail_block umfdl_mem_free_tail_block +#define UMF_mem_init_memoryspace umfdl_mem_init_memoryspace +#define UMF_realloc umf_l_realloc +#define UMF_report_perm umf_l_report_perm +#define UMF_report_vector umfdl_report_vector +#define UMF_row_search umfdl_row_search +#define UMF_scale umfdl_scale +#define UMF_scale_column umfdl_scale_column +#define UMF_set_stats umf_l_set_stats +#define UMF_singletons umf_l_singletons +#define UMF_solve umfdl_solve +#define UMF_start_front umfdl_start_front +#define UMF_store_lu umfdl_store_lu +#define UMF_store_lu_drop umfdl_store_lu_drop +#define UMF_symbolic_usage umfdl_symbolic_usage +#define UMF_transpose umfdl_transpose +#define UMF_tuple_lengths umfdl_tuple_lengths +#define UMF_usolve umfdl_usolve +#define UMF_utsolve umfdl_utsolve +#define UMF_uhsolve umfdl_uhsolve +#define UMF_valid_numeric umfdl_valid_numeric +#define UMF_valid_symbolic umfdl_valid_symbolic +#define UMF_triplet_map_x umfdl_triplet_map_x +#define UMF_triplet_map_nox umfdl_triplet_map_nox +#define UMF_triplet_nomap_x umfdl_triplet_nomap_x +#define UMF_triplet_nomap_nox umfdl_triplet_nomap_nox +#define UMF_2by2 umfdl_2by2 + +#define UMFPACK_col_to_triplet umfpack_dl_col_to_triplet +#define UMFPACK_defaults umfpack_dl_defaults +#define UMFPACK_free_numeric umfpack_dl_free_numeric +#define UMFPACK_free_symbolic umfpack_dl_free_symbolic +#define UMFPACK_get_lunz umfpack_dl_get_lunz +#define UMFPACK_get_numeric umfpack_dl_get_numeric +#define UMFPACK_get_symbolic umfpack_dl_get_symbolic +#define UMFPACK_get_determinant umfpack_dl_get_determinant +#define UMFPACK_numeric umfpack_dl_numeric +#define UMFPACK_qsymbolic umfpack_dl_qsymbolic +#define UMFPACK_report_control umfpack_dl_report_control +#define UMFPACK_report_info umfpack_dl_report_info +#define UMFPACK_report_matrix umfpack_dl_report_matrix +#define UMFPACK_report_numeric umfpack_dl_report_numeric +#define UMFPACK_report_perm umfpack_dl_report_perm +#define UMFPACK_report_status umfpack_dl_report_status +#define UMFPACK_report_symbolic umfpack_dl_report_symbolic +#define UMFPACK_report_triplet umfpack_dl_report_triplet +#define UMFPACK_report_vector umfpack_dl_report_vector +#define UMFPACK_save_numeric umfpack_dl_save_numeric +#define UMFPACK_save_symbolic umfpack_dl_save_symbolic +#define UMFPACK_load_numeric umfpack_dl_load_numeric +#define UMFPACK_load_symbolic umfpack_dl_load_symbolic +#define UMFPACK_scale umfpack_dl_scale +#define UMFPACK_solve umfpack_dl_solve +#define UMFPACK_symbolic umfpack_dl_symbolic +#define UMFPACK_transpose umfpack_dl_transpose +#define UMFPACK_triplet_to_col umfpack_dl_triplet_to_col +#define UMFPACK_wsolve umfpack_dl_wsolve + +/* for debugging only: */ +#define UMF_malloc_count umf_l_malloc_count +#define UMF_debug umfdl_debug +#define UMF_allocfail umfdl_allocfail +#define UMF_gprob umfdl_gprob +#define UMF_dump_dense umfdl_dump_dense +#define UMF_dump_element umfdl_dump_element +#define UMF_dump_rowcol umfdl_dump_rowcol +#define UMF_dump_matrix umfdl_dump_matrix +#define UMF_dump_current_front umfdl_dump_current_front +#define UMF_dump_lu umfdl_dump_lu +#define UMF_dump_memory umfdl_dump_memory +#define UMF_dump_packed_memory umfdl_dump_packed_memory +#define UMF_dump_col_matrix umfdl_dump_col_matrix +#define UMF_dump_chain umfdl_dump_chain +#define UMF_dump_start umfdl_dump_start +#define UMF_dump_rowmerge umfdl_dump_rowmerge +#define UMF_dump_diagonal_map umfdl_dump_diagonal_map + +#endif + +/* -------------------------------------------------------------------------- */ +/* Complex double precision, with int's as integers */ +/* -------------------------------------------------------------------------- */ + +#ifdef ZINT + +#define UMF_analyze umf_i_analyze +#define UMF_apply_order umf_i_apply_order +#define UMF_assemble umfzi_assemble +#define UMF_assemble_fixq umfzi_assemble_fixq +#define UMF_blas3_update umfzi_blas3_update +#define UMF_build_tuples umfzi_build_tuples +#define UMF_build_tuples_usage umfzi_build_tuples_usage +#define UMF_colamd umf_i_colamd +#define UMF_colamd_set_defaults umf_i_colamd_set_defaults +#define UMF_create_element umfzi_create_element +#define UMF_extend_front umfzi_extend_front +#define UMF_free umf_i_free +#define UMF_fsize umf_i_fsize +#define UMF_garbage_collection umfzi_garbage_collection +#define UMF_get_memory umfzi_get_memory +#define UMF_grow_front umfzi_grow_front +#define UMF_init_front umfzi_init_front +#define UMF_is_permutation umf_i_is_permutation +#define UMF_kernel umfzi_kernel +#define UMF_kernel_init umfzi_kernel_init +#define UMF_kernel_init_usage umfzi_kernel_init_usage +#define UMF_kernel_wrapup umfzi_kernel_wrapup +#define UMF_local_search umfzi_local_search +#define UMF_lsolve umfzi_lsolve +#define UMF_ltsolve umfzi_ltsolve +#define UMF_lhsolve umfzi_lhsolve +#define UMF_malloc umf_i_malloc +#define UMF_mem_alloc_element umfzi_mem_alloc_element +#define UMF_mem_alloc_head_block umfzi_mem_alloc_head_block +#define UMF_mem_alloc_tail_block umfzi_mem_alloc_tail_block +#define UMF_mem_free_tail_block umfzi_mem_free_tail_block +#define UMF_mem_init_memoryspace umfzi_mem_init_memoryspace +#define UMF_realloc umf_i_realloc +#define UMF_report_perm umf_i_report_perm +#define UMF_report_vector umfzi_report_vector +#define UMF_row_search umfzi_row_search +#define UMF_scale umfzi_scale +#define UMF_scale_column umfzi_scale_column +#define UMF_set_stats umfzi_set_stats +#define UMF_singletons umf_i_singletons +#define UMF_solve umfzi_solve +#define UMF_start_front umfzi_start_front +#define UMF_store_lu umfzi_store_lu +#define UMF_store_lu_drop umfzi_store_lu_drop +#define UMF_symbolic_usage umfzi_symbolic_usage +#define UMF_transpose umfzi_transpose +#define UMF_tuple_lengths umfzi_tuple_lengths +#define UMF_usolve umfzi_usolve +#define UMF_utsolve umfzi_utsolve +#define UMF_uhsolve umfzi_uhsolve +#define UMF_valid_numeric umfzi_valid_numeric +#define UMF_valid_symbolic umfzi_valid_symbolic +#define UMF_triplet_map_x umfzi_triplet_map_x +#define UMF_triplet_map_nox umfzi_triplet_map_nox +#define UMF_triplet_nomap_x umfzi_triplet_nomap_x +#define UMF_triplet_nomap_nox umfzi_triplet_nomap_nox +#define UMF_2by2 umfzi_2by2 + +#define UMFPACK_col_to_triplet umfpack_zi_col_to_triplet +#define UMFPACK_defaults umfpack_zi_defaults +#define UMFPACK_free_numeric umfpack_zi_free_numeric +#define UMFPACK_free_symbolic umfpack_zi_free_symbolic +#define UMFPACK_get_lunz umfpack_zi_get_lunz +#define UMFPACK_get_numeric umfpack_zi_get_numeric +#define UMFPACK_get_symbolic umfpack_zi_get_symbolic +#define UMFPACK_get_determinant umfpack_zi_get_determinant +#define UMFPACK_numeric umfpack_zi_numeric +#define UMFPACK_qsymbolic umfpack_zi_qsymbolic +#define UMFPACK_report_control umfpack_zi_report_control +#define UMFPACK_report_info umfpack_zi_report_info +#define UMFPACK_report_matrix umfpack_zi_report_matrix +#define UMFPACK_report_numeric umfpack_zi_report_numeric +#define UMFPACK_report_perm umfpack_zi_report_perm +#define UMFPACK_report_status umfpack_zi_report_status +#define UMFPACK_report_symbolic umfpack_zi_report_symbolic +#define UMFPACK_report_triplet umfpack_zi_report_triplet +#define UMFPACK_report_vector umfpack_zi_report_vector +#define UMFPACK_save_numeric umfpack_zi_save_numeric +#define UMFPACK_save_symbolic umfpack_zi_save_symbolic +#define UMFPACK_load_numeric umfpack_zi_load_numeric +#define UMFPACK_load_symbolic umfpack_zi_load_symbolic +#define UMFPACK_scale umfpack_zi_scale +#define UMFPACK_solve umfpack_zi_solve +#define UMFPACK_symbolic umfpack_zi_symbolic +#define UMFPACK_transpose umfpack_zi_transpose +#define UMFPACK_triplet_to_col umfpack_zi_triplet_to_col +#define UMFPACK_wsolve umfpack_zi_wsolve + +/* for debugging only: */ +#define UMF_malloc_count umf_i_malloc_count +#define UMF_debug umfzi_debug +#define UMF_allocfail umfzi_allocfail +#define UMF_gprob umfzi_gprob +#define UMF_dump_dense umfzi_dump_dense +#define UMF_dump_element umfzi_dump_element +#define UMF_dump_rowcol umfzi_dump_rowcol +#define UMF_dump_matrix umfzi_dump_matrix +#define UMF_dump_current_front umfzi_dump_current_front +#define UMF_dump_lu umfzi_dump_lu +#define UMF_dump_memory umfzi_dump_memory +#define UMF_dump_packed_memory umfzi_dump_packed_memory +#define UMF_dump_col_matrix umfzi_dump_col_matrix +#define UMF_dump_chain umfzi_dump_chain +#define UMF_dump_start umfzi_dump_start +#define UMF_dump_rowmerge umfzi_dump_rowmerge +#define UMF_dump_diagonal_map umfzi_dump_diagonal_map + +#endif + +/* -------------------------------------------------------------------------- */ +/* Complex double precision, with long's as integers */ +/* -------------------------------------------------------------------------- */ + +#ifdef ZLONG + +#define UMF_analyze umf_l_analyze +#define UMF_apply_order umf_l_apply_order +#define UMF_assemble umfzl_assemble +#define UMF_assemble_fixq umfzl_assemble_fixq +#define UMF_blas3_update umfzl_blas3_update +#define UMF_build_tuples umfzl_build_tuples +#define UMF_build_tuples_usage umfzl_build_tuples_usage +#define UMF_colamd umf_l_colamd +#define UMF_colamd_set_defaults umf_l_colamd_set_defaults +#define UMF_create_element umfzl_create_element +#define UMF_extend_front umfzl_extend_front +#define UMF_free umf_l_free +#define UMF_fsize umf_l_fsize +#define UMF_garbage_collection umfzl_garbage_collection +#define UMF_get_memory umfzl_get_memory +#define UMF_grow_front umfzl_grow_front +#define UMF_init_front umfzl_init_front +#define UMF_is_permutation umf_l_is_permutation +#define UMF_kernel umfzl_kernel +#define UMF_kernel_init umfzl_kernel_init +#define UMF_kernel_init_usage umfzl_kernel_init_usage +#define UMF_kernel_wrapup umfzl_kernel_wrapup +#define UMF_local_search umfzl_local_search +#define UMF_lsolve umfzl_lsolve +#define UMF_ltsolve umfzl_ltsolve +#define UMF_lhsolve umfzl_lhsolve +#define UMF_malloc umf_l_malloc +#define UMF_mem_alloc_element umfzl_mem_alloc_element +#define UMF_mem_alloc_head_block umfzl_mem_alloc_head_block +#define UMF_mem_alloc_tail_block umfzl_mem_alloc_tail_block +#define UMF_mem_free_tail_block umfzl_mem_free_tail_block +#define UMF_mem_init_memoryspace umfzl_mem_init_memoryspace +#define UMF_realloc umf_l_realloc +#define UMF_report_perm umf_l_report_perm +#define UMF_report_vector umfzl_report_vector +#define UMF_row_search umfzl_row_search +#define UMF_scale umfzl_scale +#define UMF_scale_column umfzl_scale_column +#define UMF_set_stats umfzl_set_stats +#define UMF_singletons umf_l_singletons +#define UMF_solve umfzl_solve +#define UMF_start_front umfzl_start_front +#define UMF_store_lu umfzl_store_lu +#define UMF_store_lu_drop umfzl_store_lu_drop +#define UMF_symbolic_usage umfzl_symbolic_usage +#define UMF_transpose umfzl_transpose +#define UMF_tuple_lengths umfzl_tuple_lengths +#define UMF_usolve umfzl_usolve +#define UMF_utsolve umfzl_utsolve +#define UMF_uhsolve umfzl_uhsolve +#define UMF_valid_numeric umfzl_valid_numeric +#define UMF_valid_symbolic umfzl_valid_symbolic +#define UMF_triplet_map_x umfzl_triplet_map_x +#define UMF_triplet_map_nox umfzl_triplet_map_nox +#define UMF_triplet_nomap_x umfzl_triplet_nomap_x +#define UMF_triplet_nomap_nox umfzl_triplet_nomap_nox +#define UMF_2by2 umfzl_2by2 + +#define UMFPACK_col_to_triplet umfpack_zl_col_to_triplet +#define UMFPACK_defaults umfpack_zl_defaults +#define UMFPACK_free_numeric umfpack_zl_free_numeric +#define UMFPACK_free_symbolic umfpack_zl_free_symbolic +#define UMFPACK_get_lunz umfpack_zl_get_lunz +#define UMFPACK_get_numeric umfpack_zl_get_numeric +#define UMFPACK_get_symbolic umfpack_zl_get_symbolic +#define UMFPACK_get_determinant umfpack_zl_get_determinant +#define UMFPACK_numeric umfpack_zl_numeric +#define UMFPACK_qsymbolic umfpack_zl_qsymbolic +#define UMFPACK_report_control umfpack_zl_report_control +#define UMFPACK_report_info umfpack_zl_report_info +#define UMFPACK_report_matrix umfpack_zl_report_matrix +#define UMFPACK_report_numeric umfpack_zl_report_numeric +#define UMFPACK_report_perm umfpack_zl_report_perm +#define UMFPACK_report_status umfpack_zl_report_status +#define UMFPACK_report_symbolic umfpack_zl_report_symbolic +#define UMFPACK_report_triplet umfpack_zl_report_triplet +#define UMFPACK_report_vector umfpack_zl_report_vector +#define UMFPACK_save_numeric umfpack_zl_save_numeric +#define UMFPACK_save_symbolic umfpack_zl_save_symbolic +#define UMFPACK_load_numeric umfpack_zl_load_numeric +#define UMFPACK_load_symbolic umfpack_zl_load_symbolic +#define UMFPACK_scale umfpack_zl_scale +#define UMFPACK_solve umfpack_zl_solve +#define UMFPACK_symbolic umfpack_zl_symbolic +#define UMFPACK_transpose umfpack_zl_transpose +#define UMFPACK_triplet_to_col umfpack_zl_triplet_to_col +#define UMFPACK_wsolve umfpack_zl_wsolve + +/* for debugging only: */ +#define UMF_malloc_count umf_l_malloc_count +#define UMF_debug umfzl_debug +#define UMF_allocfail umfzl_allocfail +#define UMF_gprob umfzl_gprob +#define UMF_dump_dense umfzl_dump_dense +#define UMF_dump_element umfzl_dump_element +#define UMF_dump_rowcol umfzl_dump_rowcol +#define UMF_dump_matrix umfzl_dump_matrix +#define UMF_dump_current_front umfzl_dump_current_front +#define UMF_dump_lu umfzl_dump_lu +#define UMF_dump_memory umfzl_dump_memory +#define UMF_dump_packed_memory umfzl_dump_packed_memory +#define UMF_dump_col_matrix umfzl_dump_col_matrix +#define UMF_dump_chain umfzl_dump_chain +#define UMF_dump_start umfzl_dump_start +#define UMF_dump_rowmerge umfzl_dump_rowmerge +#define UMF_dump_diagonal_map umfzl_dump_diagonal_map + +#endif diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_col_to_triplet.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_col_to_triplet.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_col_to_triplet.c @@ -0,0 +1,72 @@ +/* ========================================================================== */ +/* === UMFPACK_col_to_triplet =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User callable. Converts a column-oriented input matrix to triplet form by + constructing the column indices Tj from the column pointers Ap. The matrix + may be singular. See umfpack_col_to_triplet.h for details. + +*/ + +#include "umf_internal.h" + +GLOBAL Int UMFPACK_col_to_triplet +( + Int n_col, + const Int Ap [ ], + Int Tj [ ] +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int nz, j, p, p1, p2, length ; + + /* ---------------------------------------------------------------------- */ + /* construct the column indices */ + /* ---------------------------------------------------------------------- */ + + if (!Ap || !Tj) + { + return (UMFPACK_ERROR_argument_missing) ; + } + if (n_col <= 0) + { + return (UMFPACK_ERROR_n_nonpositive) ; + } + if (Ap [0] != 0) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + nz = Ap [n_col] ; + if (nz < 0) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + + for (j = 0 ; j < n_col ; j++) + { + p1 = Ap [j] ; + p2 = Ap [j+1] ; + length = p2 - p1 ; + if (length < 0 || p2 > nz) + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + for (p = p1 ; p < p2 ; p++) + { + Tj [p] = j ; + } + } + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_defaults.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_defaults.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_defaults.c @@ -0,0 +1,118 @@ +/* ========================================================================== */ +/* === UMFPACK_defaults ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Sets default control parameters. See umfpack_defaults.h + for details. +*/ + +#include "umf_internal.h" + +GLOBAL void UMFPACK_defaults +( + double Control [UMFPACK_CONTROL] +) +{ + Int i ; + + if (!Control) + { + /* silently return if no Control array */ + return ; + } + + for (i = 0 ; i < UMFPACK_CONTROL ; i++) + { + Control [i] = 0 ; + } + + /* ---------------------------------------------------------------------- */ + /* default control settings: can be modified at run-time */ + /* ---------------------------------------------------------------------- */ + + /* used in UMFPACK_report_* routines: */ + Control [UMFPACK_PRL] = UMFPACK_DEFAULT_PRL ; + + /* used in UMFPACK_*symbolic: */ + Control [UMFPACK_DENSE_ROW] = UMFPACK_DEFAULT_DENSE_ROW ; + Control [UMFPACK_DENSE_COL] = UMFPACK_DEFAULT_DENSE_COL ; + Control [UMFPACK_AMD_DENSE] = UMFPACK_DEFAULT_AMD_DENSE ; + Control [UMFPACK_STRATEGY] = UMFPACK_DEFAULT_STRATEGY ; + Control [UMFPACK_2BY2_TOLERANCE] = UMFPACK_DEFAULT_2BY2_TOLERANCE ; + Control [UMFPACK_AGGRESSIVE] = UMFPACK_DEFAULT_AGGRESSIVE ; + + /* used in UMFPACK_numeric: */ + Control [UMFPACK_PIVOT_TOLERANCE] = UMFPACK_DEFAULT_PIVOT_TOLERANCE ; + Control [UMFPACK_SYM_PIVOT_TOLERANCE] = UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE; + Control [UMFPACK_BLOCK_SIZE] = UMFPACK_DEFAULT_BLOCK_SIZE ; + Control [UMFPACK_ALLOC_INIT] = UMFPACK_DEFAULT_ALLOC_INIT ; + Control [UMFPACK_FRONT_ALLOC_INIT] = UMFPACK_DEFAULT_FRONT_ALLOC_INIT ; + Control [UMFPACK_SCALE] = UMFPACK_DEFAULT_SCALE ; + + /* used in UMFPACK_*solve: */ + Control [UMFPACK_IRSTEP] = UMFPACK_DEFAULT_IRSTEP ; + + /* ---------------------------------------------------------------------- */ + /* compile-time settings: cannot be modified at run-time */ + /* ---------------------------------------------------------------------- */ + +#ifdef USE_NO_BLAS + /* do not use the BLAS - use in-line C code instead */ + Control [UMFPACK_COMPILED_WITH_BLAS] = 0 ; +#else + /* use externally-provided BLAS (dgemm, dger, dgemv, zgemm, zgeru, zgemv) */ + Control [UMFPACK_COMPILED_WITH_BLAS] = 1 ; +#endif + +#ifdef MATLAB_MEX_FILE + /* use mxMalloc, mxFree, mxRealloc, and mexPrintf */ + /* use mxAssert if debugging is enabled */ + Control [UMFPACK_COMPILED_FOR_MATLAB] = 1 ; +#else +#ifdef MATHWORKS + /* use internal utMalloc, utFree, utRealloc, and utPrintf routines. */ + /* use utDivideComplex and utFdlibm_hypot for complex version. */ + /* use utAssert if debugging is enabled. */ + Control [UMFPACK_COMPILED_FOR_MATLAB] = 2 ; +#else + /* use ANSI C malloc, free, realloc, and print */ + /* use ANSI C assert if debugging is enabled */ + Control [UMFPACK_COMPILED_FOR_MATLAB] = 0 ; +#endif +#endif + +#ifdef NO_TIMER + /* no timer used */ + Control [UMFPACK_COMPILED_WITH_GETRUSAGE] = 3 ; +#ifndef NPOSIX + /* uses the POSIX sysconf ( ) and times ( ) routines in UMFPACK_tic, toc */ + Control [UMFPACK_COMPILED_WITH_GETRUSAGE] = 2 ; +#else +#ifdef GETRUSAGE + /* uses the non-standard getrusage to get CPU time (Solaris) */ + Control [UMFPACK_COMPILED_WITH_GETRUSAGE] = 1 ; +#else + /* uses the ANSI standard clock routine to get CPU time */ + /* this may wrap around */ + Control [UMFPACK_COMPILED_WITH_GETRUSAGE] = 0 ; +#endif +#endif +#endif + +#ifndef NDEBUG + /* UMFPACK is compiled in debug mode. */ + /* This is exceedingly slow. */ + DEBUG0 (("UMFPACK is running in debug mode. This is very slow!\n")) ; + Control [UMFPACK_COMPILED_IN_DEBUG_MODE] = 1 ; +#else + /* UMFPACK is compiled in normal (non-debug) mode */ + Control [UMFPACK_COMPILED_IN_DEBUG_MODE] = 0 ; +#endif +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_numeric.c @@ -0,0 +1,57 @@ +/* ========================================================================== */ +/* === UMFPACK_free_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* User-callable. Free the entire Numeric object (consists of 11 to 13 + * malloc'd objects. See UMFPACK_free_numeric.h for details. + */ + +#include "umf_internal.h" +#include "umf_free.h" + +GLOBAL void UMFPACK_free_numeric +( + void **NumericHandle +) +{ + + NumericType *Numeric ; + if (!NumericHandle) + { + return ; + } + Numeric = *((NumericType **) NumericHandle) ; + if (!Numeric) + { + return ; + } + + /* these 9 objects always exist */ + (void) UMF_free ((void *) Numeric->D) ; + (void) UMF_free ((void *) Numeric->Rperm) ; + (void) UMF_free ((void *) Numeric->Cperm) ; + (void) UMF_free ((void *) Numeric->Lpos) ; + (void) UMF_free ((void *) Numeric->Lilen) ; + (void) UMF_free ((void *) Numeric->Lip) ; + (void) UMF_free ((void *) Numeric->Upos) ; + (void) UMF_free ((void *) Numeric->Uilen) ; + (void) UMF_free ((void *) Numeric->Uip) ; + + /* Rs does not exist if scaling was not performed */ + (void) UMF_free ((void *) Numeric->Rs) ; + + /* Upattern can only exist for singular or rectangular matrices */ + (void) UMF_free ((void *) Numeric->Upattern) ; + + /* these 2 objects always exist */ + (void) UMF_free ((void *) Numeric->Memory) ; + (void) UMF_free ((void *) Numeric) ; + + *NumericHandle = (void *) NULL ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_free_symbolic.c @@ -0,0 +1,56 @@ +/* ========================================================================== */ +/* === UMFPACK_free_symbolic ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. See umfpack_free_symbolic.h for details. + All 10 objects comprising the Symbolic object are free'd via UMF_free. +*/ + +#include "umf_internal.h" +#include "umf_free.h" + +GLOBAL void UMFPACK_free_symbolic +( + void **SymbolicHandle +) +{ + + SymbolicType *Symbolic ; + if (!SymbolicHandle) + { + return ; + } + Symbolic = *((SymbolicType **) SymbolicHandle) ; + if (!Symbolic) + { + return ; + } + + (void) UMF_free ((void *) Symbolic->Cperm_init) ; + (void) UMF_free ((void *) Symbolic->Rperm_init) ; + (void) UMF_free ((void *) Symbolic->Front_npivcol) ; + (void) UMF_free ((void *) Symbolic->Front_parent) ; + (void) UMF_free ((void *) Symbolic->Front_1strow) ; + (void) UMF_free ((void *) Symbolic->Front_leftmostdesc) ; + (void) UMF_free ((void *) Symbolic->Chain_start) ; + (void) UMF_free ((void *) Symbolic->Chain_maxrows) ; + (void) UMF_free ((void *) Symbolic->Chain_maxcols) ; + (void) UMF_free ((void *) Symbolic->Cdeg) ; + (void) UMF_free ((void *) Symbolic->Rdeg) ; + + /* only when dense rows are present */ + (void) UMF_free ((void *) Symbolic->Esize) ; + + /* only when diagonal pivoting is prefered */ + (void) UMF_free ((void *) Symbolic->Diagonal_map) ; + + (void) UMF_free ((void *) Symbolic) ; + *SymbolicHandle = (void *) NULL ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_determinant.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_determinant.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_determinant.c @@ -0,0 +1,307 @@ +/* ========================================================================== */ +/* === UMFPACK_get_determinant ============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. From the LU factors, scale factor, and permutation vectors + held in the Numeric object, calculates the determinant of the matrix A. + See umfpack_get_determinant.h for a more detailed description. + + Dynamic memory usage: calls UMF_malloc once, for a total space of + n integers, and then frees all of it via UMF_free when done. + + Contributed by David Bateman, Motorola, Nov. 2004. + Modified for V4.4, Jan. 2005. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" +#include "umf_malloc.h" +#include "umf_free.h" + +/* ========================================================================== */ +/* === rescale_determinant ================================================== */ +/* ========================================================================== */ + +/* If the mantissa is too big or too small, rescale it and change exponent */ + +PRIVATE Int rescale_determinant +( + Entry *d_mantissa, + double *d_exponent +) +{ + double d_abs ; + + ABS (d_abs, *d_mantissa) ; + + if (SCALAR_IS_ZERO (d_abs)) + { + /* the determinant is zero */ + *d_exponent = 0 ; + return (FALSE) ; + } + + if (SCALAR_IS_NAN (d_abs)) + { + /* the determinant is NaN */ + return (FALSE) ; + } + + while (d_abs < 1.) + { + SCALE (*d_mantissa, 10.0) ; + *d_exponent = *d_exponent - 1.0 ; + ABS (d_abs, *d_mantissa) ; + } + + while (d_abs >= 10.) + { + SCALE (*d_mantissa, 0.1) ; + *d_exponent = *d_exponent + 1.0 ; + ABS (d_abs, *d_mantissa) ; + } + + return (TRUE) ; +} + +/* ========================================================================== */ +/* === UMFPACK_get_determinant ============================================== */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_get_determinant +( + double *Mx, +#ifdef COMPLEX + double *Mz, +#endif + double *Ex, + void *NumericHandle, + double User_Info [UMFPACK_INFO] +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry d_mantissa, d_tmp ; + double d_exponent, Info2 [UMFPACK_INFO], one [2] = {1.0, 0.0}, d_sign ; + Entry *D ; + double *Info, *Rs ; + NumericType *Numeric ; + Int i, n, itmp, npiv, *Wi, *Rperm, *Cperm, do_scale ; + +#ifndef NRECIPROCAL + Int do_recip ; +#endif + + /* ---------------------------------------------------------------------- */ + /* check input parameters */ + /* ---------------------------------------------------------------------- */ + + if (User_Info != (double *) NULL) + { + /* return Info in user's array */ + Info = User_Info ; + } + else + { + /* no Info array passed - use local one instead */ + Info = Info2 ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + Info [i] = EMPTY ; + } + } + + Info [UMFPACK_STATUS] = UMFPACK_OK ; + + Numeric = (NumericType *) NumericHandle ; + if (!UMF_valid_numeric (Numeric)) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Numeric_object ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + if (Numeric->n_row != Numeric->n_col) + { + /* only square systems can be handled */ + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_system ; + return (UMFPACK_ERROR_invalid_system) ; + } + + if (Mx == (double *) NULL) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; + return (UMFPACK_ERROR_argument_missing) ; + } + + n = Numeric->n_row ; + + /* ---------------------------------------------------------------------- */ + /* allocate workspace */ + /* ---------------------------------------------------------------------- */ + + Wi = (Int *) UMF_malloc (n, sizeof (Int)) ; + + if (!Wi) + { + DEBUGm4 (("out of memory: get determinant\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + /* ---------------------------------------------------------------------- */ + /* compute the determinant */ + /* ---------------------------------------------------------------------- */ + + Rs = Numeric->Rs ; /* row scale factors */ + do_scale = (Rs != (double *) NULL) ; + +#ifndef NRECIPROCAL + do_recip = Numeric->do_recip ; +#endif + + d_mantissa = ((Entry *) one) [0] ; + d_exponent = 0.0 ; + D = Numeric->D ; + + /* compute product of diagonal entries of U */ + for (i = 0 ; i < n ; i++) + { + MULT (d_tmp, d_mantissa, D [i]) ; + d_mantissa = d_tmp ; + + if (!rescale_determinant (&d_mantissa, &d_exponent)) + { + /* the determinant is zero or NaN */ + Info [UMFPACK_STATUS] = UMFPACK_WARNING_singular_matrix ; + /* no need to compute the determinant of R */ + do_scale = FALSE ; + break ; + } + } + + /* compute product of diagonal entries of R (or its inverse) */ + if (do_scale) + { + for (i = 0 ; i < n ; i++) + { +#ifndef NRECIPROCAL + if (do_recip) + { + /* compute determinant of R inverse */ + SCALE_DIV (d_mantissa, Rs [i]) ; + } + else +#endif + { + /* compute determinant of R */ + SCALE (d_mantissa, Rs [i]) ; + } + if (!rescale_determinant (&d_mantissa, &d_exponent)) + { + /* the determinant is zero or NaN. This is very unlikey to + * occur here, since the scale factors for a tiny or zero row + * are set to 1. */ + Info [UMFPACK_STATUS] = UMFPACK_WARNING_singular_matrix ; + break ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* determine if P and Q are odd or even permutations */ + /* ---------------------------------------------------------------------- */ + + npiv = 0 ; + Rperm = Numeric->Rperm ; + + for (i = 0 ; i < n ; i++) + { + Wi [i] = Rperm [i] ; + } + + for (i = 0 ; i < n ; i++) + { + while (Wi [i] != i) + { + itmp = Wi [Wi [i]] ; + Wi [Wi [i]] = Wi [i] ; + Wi [i] = itmp ; + npiv++ ; + } + } + + Cperm = Numeric->Cperm ; + + for (i = 0 ; i < n ; i++) + { + Wi [i] = Cperm [i] ; + } + + for (i = 0 ; i < n ; i++) + { + while (Wi [i] != i) + { + itmp = Wi [Wi [i]] ; + Wi [Wi [i]] = Wi [i] ; + Wi [i] = itmp ; + npiv++ ; + } + } + + /* if npiv is odd, the sign is -1. if it is even, the sign is +1 */ + d_sign = (npiv % 2) ? -1. : 1. ; + + /* ---------------------------------------------------------------------- */ + /* free workspace */ + /* ---------------------------------------------------------------------- */ + + (void) UMF_free ((void *) Wi) ; + + /* ---------------------------------------------------------------------- */ + /* compute the magnitude and exponent of the determinant */ + /* ---------------------------------------------------------------------- */ + + if (Ex == (double *) NULL) + { + /* Ex is not provided, so return the entire determinant in d_mantissa */ + SCALE (d_mantissa, pow (10.0, d_exponent)) ; + } + else + { + Ex [0] = d_exponent ; + } + + Mx [0] = d_sign * REAL_COMPONENT (d_mantissa) ; + +#ifdef COMPLEX + if (SPLIT (Mz)) + { + Mz [0] = d_sign * IMAG_COMPONENT (d_mantissa) ; + } + else + { + Mx [1] = d_sign * IMAG_COMPONENT (d_mantissa) ; + } +#endif + + /* determine if the determinant has (or will) overflow or underflow */ + if (d_exponent + 1.0 > log10 (DBL_MAX)) + { + Info [UMFPACK_STATUS] = UMFPACK_WARNING_determinant_overflow ; + } + else if (d_exponent - 1.0 < log10 (DBL_MIN)) + { + Info [UMFPACK_STATUS] = UMFPACK_WARNING_determinant_underflow ; + } + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_lunz.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_lunz.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_lunz.c @@ -0,0 +1,55 @@ +/* ========================================================================== */ +/* === UMFPACK_get_lunz ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Determines the number of nonzeros in L and U, and the size + of L and U. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" + +GLOBAL Int UMFPACK_get_lunz +( + Int *lnz, + Int *unz, + Int *n_row, + Int *n_col, + Int *nz_udiag, + void *NumericHandle +) +{ + NumericType *Numeric ; + + Numeric = (NumericType *) NumericHandle ; + + if (!UMF_valid_numeric (Numeric)) + { + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + if (!lnz || !unz || !n_row || !n_col || !nz_udiag) + { + return (UMFPACK_ERROR_argument_missing) ; + } + + *n_row = Numeric->n_row ; + *n_col = Numeric->n_col ; + + /* number of nz's in L below diagonal, plus the unit diagonal of L */ + *lnz = Numeric->lnz + MIN (Numeric->n_row, Numeric->n_col) ; + + /* number of nz's in U above diagonal, plus nz's on diagaonal of U */ + *unz = Numeric->unz + Numeric->nnzpiv ; + + /* number of nz's on the diagonal */ + *nz_udiag = Numeric->nnzpiv ; + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_numeric.c @@ -0,0 +1,1057 @@ +/* ========================================================================== */ +/* === UMFPACK_get_numeric ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Gets the LU factors and the permutation vectors held in the + Numeric object. L is returned in sparse row form with sorted rows, U is + returned in sparse column form with sorted columns, and P and Q are + returned as permutation vectors. See umfpack_get_numeric.h for a more + detailed description. + + Returns TRUE if successful, FALSE if the Numeric object is invalid or + if out of memory. + + Dynamic memory usage: calls UMF_malloc twice, for a total space of + 2*n integers, and then frees all of it via UMF_free when done. + +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" +#include "umf_malloc.h" +#include "umf_free.h" + +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif + +PRIVATE void get_L +( + Int Lp [ ], + Int Lj [ ], + double Lx [ ], +#ifdef COMPLEX + double Lz [ ], +#endif + NumericType *Numeric, + Int Pattern [ ], + Int Wi [ ] +) ; + +PRIVATE void get_U +( + Int Up [ ], + Int Ui [ ], + double Ux [ ], +#ifdef COMPLEX + double Uz [ ], +#endif + NumericType *Numeric, + Int Pattern [ ], + Int Wi [ ] +) ; + +/* ========================================================================== */ +/* === UMFPACK_get_numeric ================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_get_numeric +( + Int Lp [ ], + Int Lj [ ], + double Lx [ ], +#ifdef COMPLEX + double Lz [ ], +#endif + Int Up [ ], + Int Ui [ ], + double Ux [ ], +#ifdef COMPLEX + double Uz [ ], +#endif + Int P [ ], + Int Q [ ], + double Dx [ ], +#ifdef COMPLEX + double Dz [ ], +#endif + Int *p_do_recip, + double Rs [ ], + void *NumericHandle +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + NumericType *Numeric ; + Int getL, getU, *Rperm, *Cperm, k, nn, n_row, n_col, *Wi, *Pattern, + n_inner ; + double *Rs1 ; + Entry *D ; + +#ifndef NDEBUG + init_count = UMF_malloc_count ; +#endif + + Wi = (Int *) NULL ; + Pattern = (Int *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* check input parameters */ + /* ---------------------------------------------------------------------- */ + + Numeric = (NumericType *) NumericHandle ; + if (!UMF_valid_numeric (Numeric)) + { + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + n_row = Numeric->n_row ; + n_col = Numeric->n_col ; + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + + /* ---------------------------------------------------------------------- */ + /* allocate workspace */ + /* ---------------------------------------------------------------------- */ + + getL = Lp && Lj && Lx ; + getU = Up && Ui && Ux ; + + if (getL || getU) + { + Wi = (Int *) UMF_malloc (nn, sizeof (Int)) ; + Pattern = (Int *) UMF_malloc (nn, sizeof (Int)) ; + if (!Wi || !Pattern) + { + (void) UMF_free ((void *) Wi) ; + (void) UMF_free ((void *) Pattern) ; + ASSERT (UMF_malloc_count == init_count) ; + DEBUGm4 (("out of memory: get numeric\n")) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + ASSERT (UMF_malloc_count == init_count + 2) ; + } + + /* ---------------------------------------------------------------------- */ + /* get contents of Numeric */ + /* ---------------------------------------------------------------------- */ + + if (P != (Int *) NULL) + { + Rperm = Numeric->Rperm ; + for (k = 0 ; k < n_row ; k++) + { + P [k] = Rperm [k] ; + } + } + + if (Q != (Int *) NULL) + { + Cperm = Numeric->Cperm ; + for (k = 0 ; k < n_col ; k++) + { + Q [k] = Cperm [k] ; + } + } + + if (getL) + { + get_L (Lp, Lj, Lx, +#ifdef COMPLEX + Lz, +#endif + Numeric, Pattern, Wi) ; + } + + if (getU) + { + get_U (Up, Ui, Ux, +#ifdef COMPLEX + Uz, +#endif + Numeric, Pattern, Wi) ; + } + + if (Dx != (double *) NULL) + { + D = Numeric->D ; +#ifdef COMPLEX + if (SPLIT (Dz)) + { + for (k = 0 ; k < n_inner ; k++) + { + Dx [k] = REAL_COMPONENT (D [k]) ; + Dz [k] = IMAG_COMPONENT (D [k]) ; + } + } + else + { + for (k = 0 ; k < n_inner ; k++) + { + Dx [2*k ] = REAL_COMPONENT (D [k]) ; + Dx [2*k+1] = IMAG_COMPONENT (D [k]) ; + } + } +#else + { + D = Numeric->D ; + for (k = 0 ; k < n_inner ; k++) + { + Dx [k] = D [k] ; + } + } +#endif + } + + /* return the flag stating whether the scale factors are to be multiplied, + * or divided. If do_recip is TRUE, multiply. Otherwise, divided. + * If NRECIPROCAL is defined at compile time, the scale factors are always + * to be used by dividing. + */ + if (p_do_recip != (Int *) NULL) + { +#ifndef NRECIPROCAL + *p_do_recip = Numeric->do_recip ; +#else + *p_do_recip = FALSE ; +#endif + } + + if (Rs != (double *) NULL) + { + Rs1 = Numeric->Rs ; + if (Rs1 == (double *) NULL) + { + /* R is the identity matrix. */ + for (k = 0 ; k < n_row ; k++) + { + Rs [k] = 1.0 ; + } + } + else + { + for (k = 0 ; k < n_row ; k++) + { + Rs [k] = Rs1 [k] ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* free the workspace */ + /* ---------------------------------------------------------------------- */ + + (void) UMF_free ((void *) Wi) ; + (void) UMF_free ((void *) Pattern) ; + ASSERT (UMF_malloc_count == init_count) ; + + return (UMFPACK_OK) ; +} + + +/* ========================================================================== */ +/* === get_L ================================================================ */ +/* ========================================================================== */ + +/* + The matrix L is stored in the following arrays in the Numeric object: + + Int Lpos [0..npiv] + Int Lip [0..npiv], index into Numeric->Memory + Int Lilen [0..npiv] + Unit *(Numeric->Memory), pointer to memory space holding row indices + and numerical values + + where npiv is the number of pivot entries found. If A is n_row-by-n_col, + then npiv <= MIN (n_row,n_col). + + Let L_k denote the pattern of entries in column k of L (excluding the + diagonal). + + An Lchain is a sequence of columns of L whose nonzero patterns are related. + The start of an Lchain is denoted by a negative value of Lip [k]. + + To obtain L_k: + + (1) If column k starts an Lchain, then L_k is stored in its entirety. + |Lip [k]| is an index into Numeric->Memory for the integer row indices + in L_k. The number of entries in the column is |L_k| = Lilen [k]. + This defines the pattern of the "leading" column of this chain. + Lpos [k] is not used for the first column in the chain. Column zero + is always a leading column. + + (2) If column k does not start an Lchain, then L_k is represented as a + superset of L_k-1. Define Lnew_k such that (L_k-1 - {k} union Lnew_k) + = L_k, where Lnew_k and (L_k-1)-{k} are disjoint. Lnew_k are the + entries in L_k that are not in L_k-1. Lpos [k] holds the position of + pivot row index k in the prior pattern L_k-1 (if it is present), so + that the set subtraction (L_k-1)-{k} can be computed quickly, when + computing the pattern of L_k from L_k-1. The number of new entries in + L_k is stored in Lilen [k] = |Lnew_k|. + + Note that this means we must have the pattern L_k-1 to compute L_k. + + In both cases (1) and (2), we obtain the pattern L_k. + + The numerical values are stored in Numeric->Memory, starting at the index + |Lip [k]| + Lilen [k]. It is stored in the same order as the entries + in L_k, after L_k is obtained from cases (1) or (2), above. + + The advantage of using this "packed" data structure is that it can + dramatically reduce the amount of storage needed for the pattern of L. + The disadvantage is that it can be difficult for the user to access, + and it does not match the sparse matrix data structure used in MATLAB. + Thus, this routine is provided to create a conventional sparse matrix + data structure for L, in sparse-row form. A row-form of L appears to + MATLAB to be a column-oriented from of the transpose of L. If you would + like a column-form of L, then use UMFPACK_transpose (an example of this + is in umfpackmex.c). + +*/ +/* ========================================================================== */ + +PRIVATE void get_L +( + Int Lp [ ], /* of size n_row+1 */ + Int Lj [ ], /* of size lnz, where lnz = Lp [n_row] */ + double Lx [ ], /* of size lnz */ +#ifdef COMPLEX + double Lz [ ], /* of size lnz */ +#endif + NumericType *Numeric, + Int Pattern [ ], /* workspace of size n_row */ + Int Wi [ ] /* workspace of size n_row */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry value ; + Entry *xp, *Lval ; + Int deg, *ip, j, row, n_row, n_col, n_inner, *Lpos, *Lilen, *Lip, p, llen, + lnz2, lp, newLchain, k, pos, npiv, *Li, n1 ; +#ifdef COMPLEX + Int split = SPLIT (Lz) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + DEBUG4 (("get_L start:\n")) ; + n_row = Numeric->n_row ; + n_col = Numeric->n_col ; + n_inner = MIN (n_row, n_col) ; + npiv = Numeric->npiv ; + n1 = Numeric->n1 ; + Lpos = Numeric->Lpos ; + Lilen = Numeric->Lilen ; + Lip = Numeric->Lip ; + deg = 0 ; + + /* ---------------------------------------------------------------------- */ + /* count the nonzeros in each row of L */ + /* ---------------------------------------------------------------------- */ + +#pragma ivdep + for (row = 0 ; row < n_inner ; row++) + { + /* include the diagonal entry in the row counts */ + Wi [row] = 1 ; + } +#pragma ivdep + for (row = n_inner ; row < n_row ; row++) + { + Wi [row] = 0 ; + } + + /* singletons */ + for (k = 0 ; k < n1 ; k++) + { + DEBUG4 (("Singleton k "ID"\n", k)) ; + deg = Lilen [k] ; + if (deg > 0) + { + lp = Lip [k] ; + Li = (Int *) (Numeric->Memory + lp) ; + lp += UNITS (Int, deg) ; + Lval = (Entry *) (Numeric->Memory + lp) ; + for (j = 0 ; j < deg ; j++) + { + row = Li [j] ; + value = Lval [j] ; + DEBUG4 ((" row "ID" k "ID" value", row, k)) ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + Wi [row]++ ; + } + } + } + } + + /* non-singletons */ + for (k = n1 ; k < npiv ; k++) + { + + /* ------------------------------------------------------------------ */ + /* make column of L in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + lp = Lip [k] ; + newLchain = (lp < 0) ; + if (newLchain) + { + lp = -lp ; + deg = 0 ; + DEBUG4 (("start of chain for column of L\n")) ; + } + + /* remove pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n", + k, Pattern [pos], pos)) ; + ASSERT (!newLchain) ; + ASSERT (deg > 0) ; + ASSERT (pos >= 0 && pos < deg) ; + ASSERT (Pattern [pos] == k) ; + Pattern [pos] = Pattern [--deg] ; + } + + /* concatenate the pattern */ + ip = (Int *) (Numeric->Memory + lp) ; + llen = Lilen [k] ; + for (j = 0 ; j < llen ; j++) + { + row = *ip++ ; + DEBUG4 ((" row "ID" k "ID"\n", row, k)) ; + ASSERT (row > k && row < n_row) ; + Pattern [deg++] = row ; + } + + xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ; + + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ; + row = Pattern [j] ; + value = *xp++ ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + Wi [row]++ ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* construct the final row form of L */ + /* ---------------------------------------------------------------------- */ + + /* create the row pointers */ + lnz2 = 0 ; + for (row = 0 ; row < n_row ; row++) + { + Lp [row] = lnz2 ; + lnz2 += Wi [row] ; + Wi [row] = Lp [row] ; + } + Lp [n_row] = lnz2 ; + ASSERT (Numeric->lnz + n_inner == lnz2) ; + + /* add entries from the rows of L (singletons) */ + for (k = 0 ; k < n1 ; k++) + { + DEBUG4 (("Singleton k "ID"\n", k)) ; + deg = Lilen [k] ; + if (deg > 0) + { + lp = Lip [k] ; + Li = (Int *) (Numeric->Memory + lp) ; + lp += UNITS (Int, deg) ; + Lval = (Entry *) (Numeric->Memory + lp) ; + for (j = 0 ; j < deg ; j++) + { + row = Li [j] ; + value = Lval [j] ; + DEBUG4 ((" row "ID" k "ID" value", row, k)) ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + p = Wi [row]++ ; + Lj [p] = k ; +#ifdef COMPLEX + if (split) + { + + Lx [p] = REAL_COMPONENT (value) ; + Lz [p] = IMAG_COMPONENT (value) ; + } + else + { + Lx [2*p ] = REAL_COMPONENT (value) ; + Lx [2*p+1] = IMAG_COMPONENT (value) ; + } +#else + Lx [p] = value ; +#endif + } + } + } + } + + /* add entries from the rows of L (non-singletons) */ + for (k = n1 ; k < npiv ; k++) + { + + /* ------------------------------------------------------------------ */ + /* make column of L in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + lp = Lip [k] ; + newLchain = (lp < 0) ; + if (newLchain) + { + lp = -lp ; + deg = 0 ; + DEBUG4 (("start of chain for column of L\n")) ; + } + + /* remove pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n", + k, Pattern [pos], pos)) ; + ASSERT (!newLchain) ; + ASSERT (deg > 0) ; + ASSERT (pos >= 0 && pos < deg) ; + ASSERT (Pattern [pos] == k) ; + Pattern [pos] = Pattern [--deg] ; + } + + /* concatenate the pattern */ + ip = (Int *) (Numeric->Memory + lp) ; + llen = Lilen [k] ; + for (j = 0 ; j < llen ; j++) + { + row = *ip++ ; + DEBUG4 ((" row "ID" k "ID"\n", row, k)) ; + ASSERT (row > k) ; + Pattern [deg++] = row ; + } + + xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ; + + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ; + row = Pattern [j] ; + value = *xp++ ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + p = Wi [row]++ ; + Lj [p] = k ; +#ifdef COMPLEX + if (split) + { + Lx [p] = REAL_COMPONENT (value) ; + Lz [p] = IMAG_COMPONENT (value) ; + } + else + { + Lx [2*p ] = REAL_COMPONENT (value) ; + Lx [2*p+1] = IMAG_COMPONENT (value) ; + } +#else + Lx [p] = value ; +#endif + } + } + } + + /* add all of the diagonal entries (L is unit diagonal) */ + for (row = 0 ; row < n_inner ; row++) + { + p = Wi [row]++ ; + Lj [p] = row ; + +#ifdef COMPLEX + if (split) + { + Lx [p] = 1. ; + Lz [p] = 0. ; + } + else + { + Lx [2*p ] = 1. ; + Lx [2*p+1] = 0. ; + } +#else + Lx [p] = 1. ; +#endif + + ASSERT (Wi [row] == Lp [row+1]) ; + } + +#ifndef NDEBUG + DEBUG6 (("L matrix (stored by rows):")) ; + UMF_dump_col_matrix (Lx, +#ifdef COMPLEX + Lz, +#endif + Lj, Lp, n_inner, n_row, Numeric->lnz+n_inner) ; +#endif + + DEBUG4 (("get_L done:\n")) ; +} + + +/* ========================================================================== */ +/* === get_U ================================================================ */ +/* ========================================================================== */ + +/* + The matrix U is stored in the following arrays in the Numeric object: + + Int Upos [0..npiv] + Int Uip [0..npiv], index into Numeric->Memory + Int Uilen [0..npiv] + Unit *(Numeric->Memory), pointer to memory space holding column indices + and numerical values + + where npiv is the number of pivot entries found. If A is n_row-by-n_col, + then npiv <= MIN (n_row,n_col). + + Let U_k denote the pattern of entries in row k of U (excluding the + diagonal). + + A Uchain is a sequence of columns of U whose nonzero patterns are related. + The start of a Uchain is denoted by a negative value of Uip [k]. + + To obtain U_k-1: + + (1) If row k is the start of a Uchain then Uip [k] is negative and |Uip [k]| + is an index into Numeric->Memory for the integer column indices in + U_k-1. The number of entries in the row is |U_k-1| = Uilen [k]. This + defines the pattern of the "trailing" row of this chain that ends at + row k-1. + + + (2) If row k is not the start of a Uchain, then U_k-1 is a subset of U_k. + The indices in U_k are arranged so that last Uilen [k] entries of + U_k are those indices not in U_k-1. Next, the pivot column index k is + added if it appears in row U_k-1 (it never appears in U_k). Upos [k] + holds the position of pivot column index k in the pattern U_k-1 (if it + is present), so that the set union (U_k-1)+{k} can be computed quickly, + when computing the pattern of U_k-1 from U_k. + + Note that this means we must have the pattern U_k to compute L_k-1. + + In both cases (1) and (2), we obtain the pattern U_k. + + The numerical values are stored in Numeric->Memory. If k is the start of a + Uchain, then the offset is |Uip [k]| plus the size of the space needed to + store the pattern U_k-1. Otherwise, Uip [k] is the offset itself of the + numerical values, since in this case no pattern is stored. + The numerical values are stored in the same order as the entries in U_k, + after U_k is obtained from cases (1) or (2), above. + + The advantage of using this "packed" data structure is that it can + dramatically reduce the amount of storage needed for the pattern of U. + The disadvantage is that it can be difficult for the user to access, + and it does not match the sparse matrix data structure used in MATLAB. + Thus, this routine is provided to create a conventional sparse matrix + data structure for U, in sparse-column form. + +*/ +/* ========================================================================== */ + +PRIVATE void get_U +( + Int Up [ ], /* of size n_col+1 */ + Int Ui [ ], /* of size unz, where unz = Up [n_col] */ + double Ux [ ], /* of size unz */ +#ifdef COMPLEX + double Uz [ ], /* of size unz */ +#endif + NumericType *Numeric, + Int Pattern [ ], /* workspace of size n_col */ + Int Wi [ ] /* workspace of size n_col */ +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Entry value ; + Entry *xp, *D, *Uval ; + Int deg, j, *ip, col, *Upos, *Uilen, *Uip, n_col, ulen, *Usi, + unz2, p, k, up, newUchain, pos, npiv, n1 ; +#ifdef COMPLEX + Int split = SPLIT (Uz) ; +#endif +#ifndef NDEBUG + Int nnzpiv = 0 ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + DEBUG4 (("get_U start:\n")) ; + n_col = Numeric->n_col ; + n1 = Numeric->n1 ; + npiv = Numeric->npiv ; + Upos = Numeric->Upos ; + Uilen = Numeric->Uilen ; + Uip = Numeric->Uip ; + D = Numeric->D ; + + /* ---------------------------------------------------------------------- */ + /* count the nonzeros in each column of U */ + /* ---------------------------------------------------------------------- */ + + for (col = 0 ; col < npiv ; col++) + { + /* include the diagonal entry in the column counts */ + DEBUG4 (("D ["ID"] = ", col)) ; + EDEBUG4 (D [col]) ; + Wi [col] = IS_NONZERO (D [col]) ; + DEBUG4 ((" is nonzero: "ID"\n", Wi [col])) ; +#ifndef NDEBUG + nnzpiv += IS_NONZERO (D [col]) ; +#endif + } + DEBUG4 (("nnzpiv "ID" "ID"\n", nnzpiv, Numeric->nnzpiv)) ; + ASSERT (nnzpiv == Numeric->nnzpiv) ; + for (col = npiv ; col < n_col ; col++) + { + /* diagonal entries are zero for structurally singular part */ + Wi [col] = 0 ; + } + + deg = Numeric->ulen ; + if (deg > 0) + { + /* make last pivot row of U (singular matrices only) */ + DEBUG0 (("Last pivot row of U: ulen "ID"\n", deg)) ; + for (j = 0 ; j < deg ; j++) + { + Pattern [j] = Numeric->Upattern [j] ; + DEBUG0 ((" column "ID"\n", Pattern [j])) ; + } + } + + /* non-singletons */ + for (k = npiv-1 ; k >= n1 ; k--) + { + + /* ------------------------------------------------------------------ */ + /* use row k of U */ + /* ------------------------------------------------------------------ */ + + up = Uip [k] ; + ulen = Uilen [k] ; + newUchain = (up < 0) ; + if (newUchain) + { + up = -up ; + xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ; + } + else + { + xp = (Entry *) (Numeric->Memory + up) ; + } + + for (j = 0 ; j < deg ; j++) + { + DEBUG4 ((" k "ID" col "ID" value\n", k, Pattern [j])) ; + col = Pattern [j] ; + ASSERT (col >= 0 && col < n_col) ; + value = *xp++ ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + Wi [col]++ ; + } + } + + /* ------------------------------------------------------------------ */ + /* make row k-1 of U in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + if (k == n1) break ; + + if (newUchain) + { + /* next row is a new Uchain */ + deg = ulen ; + DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ; + ip = (Int *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = *ip++ ; + DEBUG4 ((" k "ID" col "ID"\n", k-1, col)) ; + ASSERT (k <= col) ; + Pattern [j] = col ; + } + } + else + { + deg -= ulen ; + DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k-1, deg)); + ASSERT (deg >= 0) ; + pos = Upos [k] ; + if (pos != EMPTY) + { + /* add the pivot column */ + DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ; + ASSERT (pos >= 0 && pos <= deg) ; + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + } + } + + /* singletons */ + for (k = n1 - 1 ; k >= 0 ; k--) + { + deg = Uilen [k] ; + DEBUG4 (("Singleton k "ID"\n", k)) ; + if (deg > 0) + { + up = Uip [k] ; + Usi = (Int *) (Numeric->Memory + up) ; + up += UNITS (Int, deg) ; + Uval = (Entry *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = Usi [j] ; + value = Uval [j] ; + DEBUG4 ((" k "ID" col "ID" value", k, col)) ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + Wi [col]++ ; + } + } + } + } + + /* ---------------------------------------------------------------------- */ + /* construct the final column form of U */ + /* ---------------------------------------------------------------------- */ + + /* create the column pointers */ + unz2 = 0 ; + for (col = 0 ; col < n_col ; col++) + { + Up [col] = unz2 ; + unz2 += Wi [col] ; + } + Up [n_col] = unz2 ; + DEBUG1 (("Numeric->unz "ID" npiv "ID" nnzpiv "ID" unz2 "ID"\n", + Numeric->unz, npiv, Numeric->nnzpiv, unz2)) ; + ASSERT (Numeric->unz + Numeric->nnzpiv == unz2) ; + + for (col = 0 ; col < n_col ; col++) + { + Wi [col] = Up [col+1] ; + } + + /* add all of the diagonal entries */ + for (col = 0 ; col < npiv ; col++) + { + if (IS_NONZERO (D [col])) + { + p = --(Wi [col]) ; + Ui [p] = col ; +#ifdef COMPLEX + if (split) + { + + Ux [p] = REAL_COMPONENT (D [col]) ; + Uz [p] = IMAG_COMPONENT (D [col]) ; + } + else + { + Ux [2*p ] = REAL_COMPONENT (D [col]) ; + Ux [2*p+1] = IMAG_COMPONENT (D [col]) ; + } +#else + Ux [p] = D [col] ; +#endif + } + } + + /* add all the entries from the rows of U */ + + deg = Numeric->ulen ; + if (deg > 0) + { + /* make last pivot row of U (singular matrices only) */ + for (j = 0 ; j < deg ; j++) + { + Pattern [j] = Numeric->Upattern [j] ; + } + } + + /* non-singletons */ + for (k = npiv-1 ; k >= n1 ; k--) + { + + /* ------------------------------------------------------------------ */ + /* use row k of U */ + /* ------------------------------------------------------------------ */ + + up = Uip [k] ; + ulen = Uilen [k] ; + newUchain = (up < 0) ; + if (newUchain) + { + up = -up ; + xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ; + } + else + { + xp = (Entry *) (Numeric->Memory + up) ; + } + + xp += deg ; + for (j = deg-1 ; j >= 0 ; j--) + { + DEBUG4 ((" k "ID" col "ID" value", k, Pattern [j])) ; + col = Pattern [j] ; + ASSERT (col >= 0 && col < n_col) ; + value = *(--xp) ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + p = --(Wi [col]) ; + Ui [p] = k ; +#ifdef COMPLEX + if (split) + { + Ux [p] = REAL_COMPONENT (value) ; + Uz [p] = IMAG_COMPONENT (value) ; + } + else + { + Ux [2*p ] = REAL_COMPONENT (value) ; + Ux [2*p+1] = IMAG_COMPONENT (value) ; + } +#else + Ux [p] = value ; +#endif + + } + } + + /* ------------------------------------------------------------------ */ + /* make row k-1 of U in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + if (newUchain) + { + /* next row is a new Uchain */ + deg = ulen ; + DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ; + ip = (Int *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = *ip++ ; + DEBUG4 ((" k "ID" col "ID"\n", k-1, col)) ; + ASSERT (k <= col) ; + Pattern [j] = col ; + } + } + else + { + deg -= ulen ; + DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k-1, deg)); + ASSERT (deg >= 0) ; + pos = Upos [k] ; + if (pos != EMPTY) + { + /* add the pivot column */ + DEBUG4 (("k "ID" add pivot entry at position "ID"\n", k, pos)) ; + ASSERT (pos >= 0 && pos <= deg) ; + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + } + } + + /* singletons */ + for (k = n1 - 1 ; k >= 0 ; k--) + { + deg = Uilen [k] ; + DEBUG4 (("Singleton k "ID"\n", k)) ; + if (deg > 0) + { + up = Uip [k] ; + Usi = (Int *) (Numeric->Memory + up) ; + up += UNITS (Int, deg) ; + Uval = (Entry *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + col = Usi [j] ; + value = Uval [j] ; + DEBUG4 ((" k "ID" col "ID" value", k, col)) ; + EDEBUG4 (value) ; + DEBUG4 (("\n")) ; + if (IS_NONZERO (value)) + { + p = --(Wi [col]) ; + Ui [p] = k ; +#ifdef COMPLEX + if (split) + { + Ux [p] = REAL_COMPONENT (value) ; + Uz [p] = IMAG_COMPONENT (value) ; + } + else + { + Ux [2*p ] = REAL_COMPONENT (value) ; + Ux [2*p+1] = IMAG_COMPONENT (value) ; + } +#else + Ux [p] = value ; +#endif + } + } + } + } + +#ifndef NDEBUG + DEBUG6 (("U matrix:")) ; + UMF_dump_col_matrix (Ux, +#ifdef COMPLEX + Uz, +#endif + Ui, Up, Numeric->n_row, n_col, Numeric->unz + Numeric->nnzpiv) ; +#endif + +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_get_symbolic.c @@ -0,0 +1,191 @@ +/* ========================================================================== */ +/* === UMFPACK_get_symbolic ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Gets the symbolic information held in the Symbolic object. + See umfpack_get_symbolic.h for a more detailed description. +*/ + +#include "umf_internal.h" +#include "umf_valid_symbolic.h" + +GLOBAL Int UMFPACK_get_symbolic +( + Int *p_n_row, + Int *p_n_col, + Int *p_n1, /* number of singletons */ + Int *p_nz, + Int *p_nfr, + Int *p_nchains, + Int P [ ], + Int Q [ ], + Int Front_npivcol [ ], + Int Front_parent [ ], + Int Front_1strow [ ], + Int Front_leftmostdesc [ ], + Int Chain_start [ ], + Int Chain_maxrows [ ], + Int Chain_maxcols [ ], + void *SymbolicHandle +) +{ + SymbolicType *Symbolic ; + Int k, n_row, n_col, n1, nfr, nchains, *p ; + + /* ---------------------------------------------------------------------- */ + /* check inputs */ + /* ---------------------------------------------------------------------- */ + + Symbolic = (SymbolicType *) SymbolicHandle ; + if (!UMF_valid_symbolic (Symbolic)) + { + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + /* ---------------------------------------------------------------------- */ + /* get contents of Symbolic */ + /* ---------------------------------------------------------------------- */ + + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + n1 = Symbolic->n1 ; + nfr = Symbolic->nfr ; + nchains = Symbolic->nchains ; + + if (p_n_row) + { + *p_n_row = n_row ; + } + + if (p_n_col) + { + *p_n_col = n_col ; + } + + if (p_n1) + { + *p_n1 = n1 ; + } + + if (p_nz) + { + *p_nz = Symbolic->nz ; + } + + if (p_nfr) + { + *p_nfr = nfr ; + } + + if (p_nchains) + { + *p_nchains = nchains ; + } + + if (P != (Int *) NULL) + { + Int *Rperm_init, *Diagonal_map ; + Rperm_init = Symbolic->Rperm_init ; + Diagonal_map = Symbolic->Diagonal_map ; + if (Diagonal_map != (Int *) NULL) + { + ASSERT (n_row == n_col) ; + /* next pivot rows are found in the diagonal map */ + for (k = 0 ; k < n_row ; k++) + { + P [k] = Rperm_init [Diagonal_map [k]] ; + } + } + else + { + /* there is no diagonal map. */ + for (k = 0 ; k < n_row ; k++) + { + P [k] = Rperm_init [k] ; + } + } + } + + if (Q != (Int *) NULL) + { + p = Symbolic->Cperm_init ; + for (k = 0 ; k < n_col ; k++) + { + Q [k] = p [k] ; + } + } + + if (Front_npivcol != (Int *) NULL) + { + p = Symbolic->Front_npivcol ; + for (k = 0 ; k <= nfr ; k++) + { + Front_npivcol [k] = p [k] ; + } + } + + if (Front_parent != (Int *) NULL) + { + p = Symbolic->Front_parent ; + for (k = 0 ; k <= nfr ; k++) + { + Front_parent [k] = p [k] ; + } + } + + if (Front_1strow != (Int *) NULL) + { + p = Symbolic->Front_1strow ; + for (k = 0 ; k <= nfr ; k++) + { + Front_1strow [k] = p [k] ; + } + } + + if (Front_leftmostdesc != (Int *) NULL) + { + p = Symbolic->Front_leftmostdesc ; + for (k = 0 ; k <= nfr ; k++) + { + Front_leftmostdesc [k] = p [k] ; + } + } + + if (Chain_start != (Int *) NULL) + { + p = Symbolic->Chain_start ; + for (k = 0 ; k <= nchains ; k++) + { + Chain_start [k] = p [k] ; + } + } + + if (Chain_maxrows != (Int *) NULL) + { + p = Symbolic->Chain_maxrows ; + for (k = 0 ; k < nchains ; k++) + { + Chain_maxrows [k] = p [k] ; + } + Chain_maxrows [nchains] = 0 ; + } + + if (Chain_maxcols != (Int *) NULL) + { + p = Symbolic->Chain_maxcols ; + for (k = 0 ; k < nchains ; k++) + { + Chain_maxcols [k] = p [k] ; + } + Chain_maxcols [nchains] = 0 ; + } + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_numeric.c @@ -0,0 +1,161 @@ +/* ========================================================================== */ +/* === UMFPACK_load_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Loads a Numeric object from a file created by + umfpack_*_save_numeric. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" +#include "umf_malloc.h" +#include "umf_free.h" + +#define READ(object,type,n) \ +{ \ + object = (type *) UMF_malloc (n, sizeof (type)) ; \ + if (object == (type *) NULL) \ + { \ + UMFPACK_free_numeric ((void **) &Numeric) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_out_of_memory) ; \ + } \ + if (fread (object, sizeof (type), n, f) != n) \ + { \ + UMFPACK_free_numeric ((void **) &Numeric) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ + if (ferror (f)) \ + { \ + UMFPACK_free_numeric ((void **) &Numeric) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ +} + +/* ========================================================================== */ +/* === UMFPACK_load_numeric ================================================= */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_load_numeric +( + void **NumericHandle, + char *user_filename +) +{ + NumericType *Numeric ; + char *filename ; + FILE *f ; + + *NumericHandle = (void *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* get the filename, or use the default name if filename is NULL */ + /* ---------------------------------------------------------------------- */ + + if (user_filename == (char *) NULL) + { + filename = "numeric.umf" ; + } + else + { + filename = user_filename ; + } + f = fopen (filename, "rb") ; + if (!f) + { + return (UMFPACK_ERROR_file_IO) ; + } + + /* ---------------------------------------------------------------------- */ + /* read the Numeric header from the file, in binary */ + /* ---------------------------------------------------------------------- */ + + Numeric = (NumericType *) UMF_malloc (1, sizeof (NumericType)) ; + if (Numeric == (NumericType *) NULL) + { + fclose (f) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + if (fread (Numeric, sizeof (NumericType), 1, f) != 1) + { + (void) UMF_free ((void *) Numeric) ; + fclose (f) ; + return (UMFPACK_ERROR_file_IO) ; + } + if (ferror (f)) + { + (void) UMF_free ((void *) Numeric) ; + fclose (f) ; + return (UMFPACK_ERROR_file_IO) ; + } + + if (Numeric->valid != NUMERIC_VALID || Numeric->n_row <= 0 || + Numeric->n_col <= 0 || Numeric->npiv < 0 || Numeric->ulen < 0 || + Numeric->size <= 0) + { + /* Numeric does not point to a NumericType object */ + (void) UMF_free ((void *) Numeric) ; + fclose (f) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + Numeric->D = (Entry *) NULL ; + Numeric->Rperm = (Int *) NULL ; + Numeric->Cperm = (Int *) NULL ; + Numeric->Lpos = (Int *) NULL ; + Numeric->Lilen = (Int *) NULL ; + Numeric->Lip = (Int *) NULL ; + Numeric->Upos = (Int *) NULL ; + Numeric->Uilen = (Int *) NULL ; + Numeric->Uip = (Int *) NULL ; + Numeric->Rs = (double *) NULL ; + Numeric->Memory = (Unit *) NULL ; + Numeric->Upattern = (Int *) NULL ; + + /* umfpack_free_numeric can now be safely called if an error occurs */ + + /* ---------------------------------------------------------------------- */ + /* read the rest of the Numeric object */ + /* ---------------------------------------------------------------------- */ + + READ (Numeric->D, Entry, MIN (Numeric->n_row, Numeric->n_col)+1) ; + READ (Numeric->Rperm, Int, Numeric->n_row+1) ; + READ (Numeric->Cperm, Int, Numeric->n_col+1) ; + READ (Numeric->Lpos, Int, Numeric->npiv+1) ; + READ (Numeric->Lilen, Int, Numeric->npiv+1) ; + READ (Numeric->Lip, Int, Numeric->npiv+1) ; + READ (Numeric->Upos, Int, Numeric->npiv+1) ; + READ (Numeric->Uilen, Int, Numeric->npiv+1) ; + READ (Numeric->Uip, Int, Numeric->npiv+1) ; + if (Numeric->scale != UMFPACK_SCALE_NONE) + { + READ (Numeric->Rs, double, Numeric->n_row) ; + } + if (Numeric->ulen > 0) + { + READ (Numeric->Upattern, Int, Numeric->ulen+1) ; + } + READ (Numeric->Memory, Unit, Numeric->size) ; + + /* close the file */ + fclose (f) ; + + /* make sure the Numeric object is valid */ + if (!UMF_valid_numeric (Numeric)) + { + UMFPACK_free_numeric ((void **) &Numeric) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + *NumericHandle = (void *) Numeric ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_load_symbolic.c @@ -0,0 +1,165 @@ +/* ========================================================================== */ +/* === UMFPACK_load_symbolic ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Loads a Symbolic object from a file created by + umfpack_*_save_symbolic. +*/ + +#include "umf_internal.h" +#include "umf_valid_symbolic.h" +#include "umf_malloc.h" +#include "umf_free.h" + +#define READ(object,type,n) \ +{ \ + object = (type *) UMF_malloc (n, sizeof (type)) ; \ + if (object == (type *) NULL) \ + { \ + UMFPACK_free_symbolic ((void **) &Symbolic) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_out_of_memory) ; \ + } \ + if (fread (object, sizeof (type), n, f) != n) \ + { \ + UMFPACK_free_symbolic ((void **) &Symbolic) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ + if (ferror (f)) \ + { \ + UMFPACK_free_symbolic ((void **) &Symbolic) ; \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ +} + +/* ========================================================================== */ +/* === UMFPACK_load_symbolic ================================================ */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_load_symbolic +( + void **SymbolicHandle, + char *user_filename +) +{ + SymbolicType *Symbolic ; + char *filename ; + FILE *f ; + + *SymbolicHandle = (void *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* get the filename, or use the default name if filename is NULL */ + /* ---------------------------------------------------------------------- */ + + if (user_filename == (char *) NULL) + { + filename = "symbolic.umf" ; + } + else + { + filename = user_filename ; + } + f = fopen (filename, "rb") ; + if (!f) + { + return (UMFPACK_ERROR_file_IO) ; + } + + /* ---------------------------------------------------------------------- */ + /* read the Symbolic header from the file, in binary */ + /* ---------------------------------------------------------------------- */ + + Symbolic = (SymbolicType *) UMF_malloc (1, sizeof (SymbolicType)) ; + if (Symbolic == (SymbolicType *) NULL) + { + fclose (f) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + if (fread (Symbolic, sizeof (SymbolicType), 1, f) != 1) + { + (void) UMF_free ((void *) Symbolic) ; + fclose (f) ; + return (UMFPACK_ERROR_file_IO) ; + } + if (ferror (f)) + { + (void) UMF_free ((void *) Symbolic) ; + fclose (f) ; + return (UMFPACK_ERROR_file_IO) ; + } + + if (Symbolic->valid != SYMBOLIC_VALID || Symbolic->n_row <= 0 || + Symbolic->n_col <= 0 || Symbolic->nfr < 0 || Symbolic->nchains < 0 || + Symbolic->esize < 0) + { + /* Symbolic does not point to a Symbolic object */ + (void) UMF_free ((void *) Symbolic) ; + fclose (f) ; + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + Symbolic->Cperm_init = (Int *) NULL ; + Symbolic->Rperm_init = (Int *) NULL ; + Symbolic->Front_npivcol = (Int *) NULL ; + Symbolic->Front_parent = (Int *) NULL ; + Symbolic->Front_1strow = (Int *) NULL ; + Symbolic->Front_leftmostdesc = (Int *) NULL ; + Symbolic->Chain_start = (Int *) NULL ; + Symbolic->Chain_maxrows = (Int *) NULL ; + Symbolic->Chain_maxcols = (Int *) NULL ; + Symbolic->Cdeg = (Int *) NULL ; + Symbolic->Rdeg = (Int *) NULL ; + Symbolic->Esize = (Int *) NULL ; + Symbolic->Diagonal_map = (Int *) NULL ; + + /* umfpack_free_symbolic can now be safely called if an error occurs */ + + /* ---------------------------------------------------------------------- */ + /* read the rest of the Symbolic object */ + /* ---------------------------------------------------------------------- */ + + READ (Symbolic->Cperm_init, Int, Symbolic->n_col+1) ; + READ (Symbolic->Rperm_init, Int, Symbolic->n_row+1) ; + READ (Symbolic->Front_npivcol, Int, Symbolic->nfr+1) ; + READ (Symbolic->Front_parent, Int, Symbolic->nfr+1) ; + READ (Symbolic->Front_1strow, Int, Symbolic->nfr+1) ; + READ (Symbolic->Front_leftmostdesc, Int, Symbolic->nfr+1) ; + READ (Symbolic->Chain_start, Int, Symbolic->nchains+1) ; + READ (Symbolic->Chain_maxrows, Int, Symbolic->nchains+1) ; + READ (Symbolic->Chain_maxcols, Int, Symbolic->nchains+1) ; + READ (Symbolic->Cdeg, Int, Symbolic->n_col+1) ; + READ (Symbolic->Rdeg, Int, Symbolic->n_row+1) ; + if (Symbolic->esize > 0) + { + /* only when dense rows are present */ + READ (Symbolic->Esize, Int, Symbolic->esize) ; + } + if (Symbolic->prefer_diagonal) + { + /* only when diagonal pivoting is prefered */ + READ (Symbolic->Diagonal_map, Int, Symbolic->n_col+1) ; + } + + /* close the file */ + fclose (f) ; + + /* make sure the Symbolic object is valid */ + if (!UMF_valid_symbolic (Symbolic)) + { + UMFPACK_free_symbolic ((void **) &Symbolic) ; + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + *SymbolicHandle = (void *) Symbolic ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_numeric.c @@ -0,0 +1,792 @@ +/* ========================================================================== */ +/* === UMFPACK_numeric ====================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Factorizes A into its LU factors, given a symbolic + pre-analysis computed by UMFPACK_symbolic. See umfpack_numeric.h for a + description. + + Dynamic memory allocation: substantial. See comments (1) through (7), + below. If an error occurs, all allocated space is free'd by UMF_free. + If successful, the Numeric object contains 11 to 13 objects allocated by + UMF_malloc that hold the LU factors of the input matrix. +*/ + +#include "umf_internal.h" +#include "umf_valid_symbolic.h" +#include "umf_set_stats.h" +#include "umf_kernel.h" +#include "umf_malloc.h" +#include "umf_free.h" +#include "umf_realloc.h" + +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif + +PRIVATE Int work_alloc +( + WorkType *Work, + SymbolicType *Symbolic +) ; + +PRIVATE void free_work +( + WorkType *Work +) ; + +PRIVATE Int numeric_alloc +( + NumericType **NumericHandle, + SymbolicType *Symbolic, + double alloc_init, + Int scale +) ; + +PRIVATE void error +( + NumericType **Numeric, + WorkType *Work +) ; + + +/* ========================================================================== */ +/* === UMFPACK_numeric ====================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_numeric +( + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + void *SymbolicHandle, + void **NumericHandle, + const double Control [UMFPACK_CONTROL], + double User_Info [UMFPACK_INFO] +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double Info2 [UMFPACK_INFO], alloc_init, relpt, relpt2, droptol, + front_alloc_init, stats [2] ; + double *Info ; + WorkType WorkSpace, *Work ; + NumericType *Numeric ; + SymbolicType *Symbolic ; + Int n_row, n_col, n_inner, newsize, i, status, *inew, npiv, ulen, scale ; + Unit *mnew ; + + /* ---------------------------------------------------------------------- */ + /* get the amount of time used by the process so far */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (stats) ; + + /* ---------------------------------------------------------------------- */ + /* initialize and check inputs */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + UMF_dump_start ( ) ; + init_count = UMF_malloc_count ; + DEBUGm4 (("\nUMFPACK numeric: U transpose version\n")) ; +#endif + + /* If front_alloc_init negative then allocate that size of front in + * UMF_start_front. If alloc_init negative, then allocate that initial + * size of Numeric->Memory. */ + + relpt = GET_CONTROL (UMFPACK_PIVOT_TOLERANCE, + UMFPACK_DEFAULT_PIVOT_TOLERANCE) ; + relpt2 = GET_CONTROL (UMFPACK_SYM_PIVOT_TOLERANCE, + UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE) ; + alloc_init = GET_CONTROL (UMFPACK_ALLOC_INIT, UMFPACK_DEFAULT_ALLOC_INIT) ; + front_alloc_init = GET_CONTROL (UMFPACK_FRONT_ALLOC_INIT, + UMFPACK_DEFAULT_FRONT_ALLOC_INIT) ; + scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ; + droptol = GET_CONTROL (UMFPACK_DROPTOL, UMFPACK_DEFAULT_DROPTOL) ; + + relpt = MAX (0.0, MIN (relpt, 1.0)) ; + relpt2 = MAX (0.0, MIN (relpt2, 1.0)) ; + droptol = MAX (0.0, droptol) ; + front_alloc_init = MIN (1.0, front_alloc_init) ; + + if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX) + { + scale = UMFPACK_DEFAULT_SCALE ; + } + + if (User_Info != (double *) NULL) + { + /* return Info in user's array */ + Info = User_Info ; + /* clear the parts of Info that are set by UMFPACK_numeric */ + for (i = UMFPACK_NUMERIC_SIZE ; i <= UMFPACK_MAX_FRONT_NCOLS ; i++) + { + Info [i] = EMPTY ; + } + for (i = UMFPACK_NUMERIC_DEFRAG ; i < UMFPACK_IR_TAKEN ; i++) + { + Info [i] = EMPTY ; + } + } + else + { + /* no Info array passed - use local one instead */ + Info = Info2 ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + Info [i] = EMPTY ; + } + } + + Symbolic = (SymbolicType *) SymbolicHandle ; + Numeric = (NumericType *) NULL ; + if (!UMF_valid_symbolic (Symbolic)) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Symbolic_object ; + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + /* compute alloc_init automatically for AMD ordering */ + if (Symbolic->ordering == UMFPACK_ORDERING_AMD && alloc_init >= 0) + { + alloc_init = (Symbolic->nz + Symbolic->amd_lunz) / Symbolic->lunz_bound; + alloc_init = MIN (1.0, alloc_init) ; + alloc_init *= UMF_REALLOC_INCREASE ; + } + + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + n_inner = MIN (n_row, n_col) ; + + /* check for integer overflow in Numeric->Memory minimum size */ + if (INT_OVERFLOW (Symbolic->dnum_mem_init_usage * sizeof (Unit))) + { + /* :: int overflow, initial Numeric->Memory size :: */ + /* There's no hope to allocate a Numeric object big enough simply to + * hold the initial matrix, so return an out-of-memory condition */ + DEBUGm4 (("out of memory: numeric int overflow\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + Info [UMFPACK_STATUS] = UMFPACK_OK ; + Info [UMFPACK_NROW] = n_row ; + Info [UMFPACK_NCOL] = n_col ; + Info [UMFPACK_SIZE_OF_UNIT] = (double) (sizeof (Unit)) ; + + if (!Ap || !Ai || !Ax || !NumericHandle) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; + return (UMFPACK_ERROR_argument_missing) ; + } + + Info [UMFPACK_NZ] = Ap [n_col] ; + *NumericHandle = (void *) NULL ; + + /* ---------------------------------------------------------------------- */ + /* allocate the Work object */ + /* ---------------------------------------------------------------------- */ + + /* (1) calls UMF_malloc 15 or 17 times, to obtain temporary workspace of + * size c+1 Entry's and 2*(n_row+1) + 3*(n_col+1) + (n_col+n_inner+1) + + * (nn+1) + * 3*(c+1) + 2*(r+1) + max(r,c) + (nfr+1) integers plus 2*nn + * more integers if diagonal pivoting is to be done. r is the maximum + * number of rows in any frontal matrix, c is the maximum number of columns + * in any frontal matrix, n_inner is min (n_row,n_col), nn is + * max (n_row,n_col), and nfr is the number of frontal matrices. For a + * square matrix, this is c+1 Entry's and about 8n + 3c + 2r + max(r,c) + + * nfr integers, plus 2n more for diagonal pivoting. + */ + + Work = &WorkSpace ; + Work->n_row = n_row ; + Work->n_col = n_col ; + Work->nfr = Symbolic->nfr ; + Work->nb = Symbolic->nb ; + Work->n1 = Symbolic->n1 ; + + if (!work_alloc (Work, Symbolic)) + { + DEBUGm4 (("out of memory: numeric work\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Numeric, Work) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + ASSERT (UMF_malloc_count == init_count + 16 + 2*Symbolic->prefer_diagonal) ; + + /* ---------------------------------------------------------------------- */ + /* allocate Numeric object */ + /* ---------------------------------------------------------------------- */ + + /* (2) calls UMF_malloc 10 or 11 times, for a total space of + * sizeof (NumericType) bytes, 4*(n_row+1) + 4*(n_row+1) integers, and + * (n_inner+1) Entry's, plus n_row Entry's if row scaling is to be done. + * sizeof (NumericType) is a small constant. Next, it calls UMF_malloc + * once, for the variable-sized part of the Numeric object + * (Numeric->Memory). The size of this object is the larger of + * (Control [UMFPACK_ALLOC_INIT]) * (the approximate upper bound computed + * by UMFPACK_symbolic), and the minimum required to start the numerical + * factorization. * This request is reduced if it fails. + */ + + if (!numeric_alloc (&Numeric, Symbolic, alloc_init, scale)) + { + DEBUGm4 (("out of memory: initial numeric\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Numeric, Work) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", + init_count, UMF_malloc_count)) ; + ASSERT (UMF_malloc_count == init_count + + (16 + 2*Symbolic->prefer_diagonal) + + (11 + (scale != UMFPACK_SCALE_NONE))) ; + + /* set control parameters */ + Numeric->relpt = relpt ; + Numeric->relpt2 = relpt2 ; + Numeric->droptol = droptol ; + Numeric->alloc_init = alloc_init ; + Numeric->front_alloc_init = front_alloc_init ; + Numeric->scale = scale ; + + DEBUG0 (("umf relpt %g %g init %g %g inc %g red %g\n", + relpt, relpt2, alloc_init, front_alloc_init, + UMF_REALLOC_INCREASE, UMF_REALLOC_REDUCTION)) ; + + /* ---------------------------------------------------------------------- */ + /* scale and factorize */ + /* ---------------------------------------------------------------------- */ + + /* (3) During numerical factorization (inside UMF_kernel), the variable-size + * block of memory is increased in size via a call to UMF_realloc if it is + * found to be too small. During factorization, this block holds the + * pattern and values of L and U at the top end, and the elements + * (contibution blocks) and the current frontal matrix (Work->F*) at the + * bottom end. The peak size of the variable-sized object is estimated in + * UMFPACK_*symbolic (Info [UMFPACK_VARIABLE_PEAK_ESTIMATE]), although this + * upper bound can be very loose. The size of the Symbolic object + * (which is currently allocated) is in Info [UMFPACK_SYMBOLIC_SIZE], and + * is between 2*n and 13*n integers. + */ + + DEBUG0 (("Calling umf_kernel\n")) ; + status = UMF_kernel (Ap, Ai, Ax, +#ifdef COMPLEX + Az, +#endif + Numeric, Work, Symbolic) ; + + Info [UMFPACK_STATUS] = status ; + if (status < UMFPACK_OK) + { + /* out of memory, or pattern has changed */ + error (&Numeric, Work) ; + return (status) ; + } + + Info [UMFPACK_FORCED_UPDATES] = Work->nforced ; + Info [UMFPACK_VARIABLE_INIT] = Numeric->init_usage ; + if (Symbolic->prefer_diagonal) + { + Info [UMFPACK_NOFF_DIAG] = Work->noff_diagonal ; + } + + DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", + init_count, UMF_malloc_count)) ; + + npiv = Numeric->npiv ; /* = n_inner for nonsingular matrices */ + ulen = Numeric->ulen ; /* = 0 for square nonsingular matrices */ + + /* ---------------------------------------------------------------------- */ + /* free Work object */ + /* ---------------------------------------------------------------------- */ + + /* (4) After numerical factorization all of the objects allocated in step + * (1) are freed via UMF_free, except that one object of size n_col+1 is + * kept if there are off-diagonal nonzeros in the last pivot row (can only + * occur for singular or rectangular matrices). This is Work->Upattern, + * which is transfered to Numeric->Upattern if ulen > 0. + */ + + DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", + init_count, UMF_malloc_count)) ; + + free_work (Work) ; + + DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", + init_count, UMF_malloc_count)) ; + DEBUG0 (("Numeric->ulen: "ID" scale: "ID"\n", ulen, scale)) ; + ASSERT (UMF_malloc_count == init_count + (ulen > 0) + + (11 + (scale != UMFPACK_SCALE_NONE))) ; + + /* ---------------------------------------------------------------------- */ + /* reduce Lpos, Lilen, Lip, Upos, Uilen and Uip to size npiv+1 */ + /* ---------------------------------------------------------------------- */ + + /* (5) Six components of the Numeric object are reduced in size if the + * matrix is singular or rectangular. The original size is 3*(n_row+1) + + * 3*(n_col+1) integers. The new size is 6*(npiv+1) integers. For + * square non-singular matrices, these two sizes are the same. + */ + + if (npiv < n_row) + { + /* reduce Lpos, Uilen, and Uip from size n_row+1 to size npiv */ + inew = (Int *) UMF_realloc (Numeric->Lpos, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Lpos = inew ; + } + inew = (Int *) UMF_realloc (Numeric->Uilen, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Uilen = inew ; + } + inew = (Int *) UMF_realloc (Numeric->Uip, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Uip = inew ; + } + } + + if (npiv < n_col) + { + /* reduce Upos, Lilen, and Lip from size n_col+1 to size npiv */ + inew = (Int *) UMF_realloc (Numeric->Upos, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Upos = inew ; + } + inew = (Int *) UMF_realloc (Numeric->Lilen, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Lilen = inew ; + } + inew = (Int *) UMF_realloc (Numeric->Lip, npiv+1, sizeof (Int)) ; + if (inew) + { + Numeric->Lip = inew ; + } + } + + /* ---------------------------------------------------------------------- */ + /* reduce Numeric->Upattern from size n_col+1 to size ulen+1 */ + /* ---------------------------------------------------------------------- */ + + /* (6) The size of Numeric->Upattern (formerly Work->Upattern) is reduced + * from size n_col+1 to size ulen + 1. If ulen is zero, the object does + * not exist. */ + + DEBUG4 (("ulen: "ID" Upattern "ID"\n", ulen, (Int) Numeric->Upattern)) ; + ASSERT (IMPLIES (ulen == 0, Numeric->Upattern == (Int *) NULL)) ; + if (ulen > 0 && ulen < n_col) + { + inew = (Int *) UMF_realloc (Numeric->Upattern, ulen+1, sizeof (Int)) ; + if (inew) + { + Numeric->Upattern = inew ; + } + } + + /* ---------------------------------------------------------------------- */ + /* reduce Numeric->Memory to hold just the LU factors at the head */ + /* ---------------------------------------------------------------------- */ + + /* (7) The variable-sized block (Numeric->Memory) is reduced to hold just L + * and U, via a call to UMF_realloc, since the frontal matrices are no + * longer needed. + */ + + newsize = Numeric->ihead ; + if (newsize < Numeric->size) + { + mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ; + if (mnew) + { + /* realloc succeeded (how can it fail since the size is reduced?) */ + Numeric->Memory = mnew ; + Numeric->size = newsize ; + } + } + Numeric->ihead = Numeric->size ; + Numeric->itail = Numeric->ihead ; + Numeric->tail_usage = 0 ; + Numeric->ibig = EMPTY ; + /* UMF_mem_alloc_tail_block can no longer be called (no tail marker) */ + + /* ---------------------------------------------------------------------- */ + /* report the results and return the Numeric object */ + /* ---------------------------------------------------------------------- */ + + UMF_set_stats ( + Info, + Symbolic, + (double) Numeric->max_usage, /* actual peak Numeric->Memory */ + (double) Numeric->size, /* actual final Numeric->Memory */ + Numeric->flops, /* actual "true flops" */ + (double) Numeric->lnz + n_inner, /* actual nz in L */ + (double) Numeric->unz + Numeric->nnzpiv, /* actual nz in U */ + (double) Numeric->maxfrsize, /* actual largest front size */ + (double) ulen, /* actual Numeric->Upattern size */ + (double) npiv, /* actual # pivots found */ + (double) Numeric->maxnrows, /* actual largest #rows in front */ + (double) Numeric->maxncols, /* actual largest #cols in front */ + scale != UMFPACK_SCALE_NONE, + Symbolic->prefer_diagonal, + ACTUAL) ; + + Info [UMFPACK_ALLOC_INIT_USED] = Numeric->alloc_init ; + Info [UMFPACK_NUMERIC_DEFRAG] = Numeric->ngarbage ; + Info [UMFPACK_NUMERIC_REALLOC] = Numeric->nrealloc ; + Info [UMFPACK_NUMERIC_COSTLY_REALLOC] = Numeric->ncostly ; + Info [UMFPACK_COMPRESSED_PATTERN] = Numeric->isize ; + Info [UMFPACK_LU_ENTRIES] = Numeric->nLentries + Numeric->nUentries + + Numeric->npiv ; + Info [UMFPACK_UDIAG_NZ] = Numeric->nnzpiv ; + Info [UMFPACK_RSMIN] = Numeric->rsmin ; + Info [UMFPACK_RSMAX] = Numeric->rsmax ; + Info [UMFPACK_WAS_SCALED] = Numeric->scale ; + + /* nz in L and U with no dropping of small entries */ + Info [UMFPACK_ALL_LNZ] = Numeric->all_lnz + n_inner ; + Info [UMFPACK_ALL_UNZ] = Numeric->all_unz + Numeric->nnzpiv ; + Info [UMFPACK_NZDROPPED] = + (Numeric->all_lnz - Numeric->lnz) + + (Numeric->all_unz - Numeric->unz) ; + + /* estimate of the reciprocal of the condition number. */ + if (SCALAR_IS_ZERO (Numeric->min_udiag) + || SCALAR_IS_ZERO (Numeric->max_udiag) + || SCALAR_IS_NAN (Numeric->min_udiag) + || SCALAR_IS_NAN (Numeric->max_udiag)) + { + /* rcond is zero if there is any zero or NaN on the diagonal */ + Numeric->rcond = 0.0 ; + } + else + { + /* estimate of the recipricol of the condition number. */ + /* This is NaN if diagonal is zero-free, but has one or more NaN's. */ + Numeric->rcond = Numeric->min_udiag / Numeric->max_udiag ; + } + Info [UMFPACK_UMIN] = Numeric->min_udiag ; + Info [UMFPACK_UMAX] = Numeric->max_udiag ; + Info [UMFPACK_RCOND] = Numeric->rcond ; + + if (Numeric->nnzpiv < n_inner + || SCALAR_IS_ZERO (Numeric->rcond) || SCALAR_IS_NAN (Numeric->rcond)) + { + /* there are zeros and/or NaN's on the diagonal of U */ + DEBUG0 (("Warning, matrix is singular in umfpack_numeric\n")) ; + DEBUG0 (("nnzpiv "ID" n_inner "ID" rcond %g\n", Numeric->nnzpiv, + n_inner, Numeric->rcond)) ; + status = UMFPACK_WARNING_singular_matrix ; + Info [UMFPACK_STATUS] = status ; + } + + Numeric->valid = NUMERIC_VALID ; + *NumericHandle = (void *) Numeric ; + + /* Numeric has 11 to 13 objects */ + ASSERT (UMF_malloc_count == init_count + 11 + + + (ulen > 0) /* Numeric->Upattern */ + + (scale != UMFPACK_SCALE_NONE)) ; /* Numeric->Rs */ + + /* ---------------------------------------------------------------------- */ + /* get the time used by UMFPACK_numeric */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (stats) ; + Info [UMFPACK_NUMERIC_WALLTIME] = stats [0] ; + Info [UMFPACK_NUMERIC_TIME] = stats [1] ; + + /* return UMFPACK_OK or UMFPACK_WARNING_singular_matrix */ + return (status) ; + +} + + +/* ========================================================================== */ +/* === numeric_alloc ======================================================== */ +/* ========================================================================== */ + +/* Allocate the Numeric object */ + +PRIVATE Int numeric_alloc +( + NumericType **NumericHandle, + SymbolicType *Symbolic, + double alloc_init, + Int scale +) +{ + double nsize, bsize ; + Int n_row, n_col, n_inner, min_usage, trying ; + NumericType *Numeric ; + + DEBUG0 (("numeric alloc:\n")) ; + + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + n_inner = MIN (n_row, n_col) ; + *NumericHandle = (NumericType *) NULL ; + + /* 1 allocation: accounted for in UMF_set_stats (num_On_size1), + * free'd in umfpack_free_numeric */ + Numeric = (NumericType *) UMF_malloc (1, sizeof (NumericType)) ; + + if (!Numeric) + { + return (FALSE) ; /* out of memory */ + } + Numeric->valid = 0 ; + *NumericHandle = Numeric ; + + /* 9 allocations: accounted for in UMF_set_stats (num_On_size1), + * free'd in umfpack_free_numeric */ + Numeric->D = (Entry *) UMF_malloc (n_inner+1, sizeof (Entry)) ; + Numeric->Rperm = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + Numeric->Cperm = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Numeric->Lpos = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + Numeric->Lilen = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Numeric->Lip = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Numeric->Upos = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Numeric->Uilen = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + Numeric->Uip = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + + /* 1 allocation if scaling: in UMF_set_stats (num_On_size1), + * free'd in umfpack_free_numeric */ + if (scale != UMFPACK_SCALE_NONE) + { + DEBUG0 (("Allocating scale factors\n")) ; + Numeric->Rs = (double *) UMF_malloc (n_row, sizeof (double)) ; + } + else + { + DEBUG0 (("No scale factors allocated (R = I)\n")) ; + Numeric->Rs = (double *) NULL ; + } + + Numeric->Memory = (Unit *) NULL ; + + /* Upattern has already been allocated as part of the Work object. If + * the matrix is singular or rectangular, and there are off-diagonal + * nonzeros in the last pivot row, then Work->Upattern is not free'd. + * Instead it is transfered to Numeric->Upattern. If it exists, + * Numeric->Upattern is free'd in umfpack_free_numeric. */ + Numeric->Upattern = (Int *) NULL ; /* used for singular matrices only */ + + if (!Numeric->D || !Numeric->Rperm || !Numeric->Cperm || !Numeric->Upos || + !Numeric->Lpos || !Numeric->Lilen || !Numeric->Uilen || !Numeric->Lip || + !Numeric->Uip || (scale != UMFPACK_SCALE_NONE && !Numeric->Rs)) + { + return (FALSE) ; /* out of memory */ + } + + /* ---------------------------------------------------------------------- */ + /* allocate initial Numeric->Memory for LU factors and elements */ + /* ---------------------------------------------------------------------- */ + + if (alloc_init < 0) + { + /* -alloc_init is the exact size to initially allocate */ + nsize = -alloc_init ; + } + else + { + /* alloc_init is a ratio of the upper bound memory usage */ + nsize = (alloc_init * Symbolic->num_mem_usage_est) + 1 ; + } + min_usage = Symbolic->num_mem_init_usage ; + + /* Numeric->Memory must be large enough for UMF_kernel_init */ + nsize = MAX (min_usage, nsize) ; + + /* Numeric->Memory cannot be larger in size than Int_MAX / sizeof(Unit) */ + /* For ILP32 mode: 2GB (nsize cannot be bigger than 256 Mwords) */ + bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ; + DEBUG0 (("bsize %g\n", bsize)) ; + nsize = MIN (nsize, bsize) ; + + Numeric->size = (Int) nsize ; + + DEBUG0 (("Num init %g usage_est %g numsize "ID" minusage "ID"\n", + alloc_init, Symbolic->num_mem_usage_est, Numeric->size, min_usage)) ; + + /* allocates 1 object: */ + /* keep trying until successful, or memory request is too small */ + trying = TRUE ; + while (trying) + { + Numeric->Memory = (Unit *) UMF_malloc (Numeric->size, sizeof (Unit)) ; + if (Numeric->Memory) + { + DEBUG0 (("Successful Numeric->size: "ID"\n", Numeric->size)) ; + return (TRUE) ; + } + /* too much, reduce the request (but not below the minimum) */ + /* and try again */ + trying = Numeric->size > min_usage ; + Numeric->size = (Int) + (UMF_REALLOC_REDUCTION * ((double) Numeric->size)) ; + Numeric->size = MAX (min_usage, Numeric->size) ; + } + + return (FALSE) ; /* we failed to allocate Numeric->Memory */ +} + + +/* ========================================================================== */ +/* === work_alloc =========================================================== */ +/* ========================================================================== */ + +/* Allocate the Work object. Return TRUE if successful. */ + +PRIVATE Int work_alloc +( + WorkType *Work, + SymbolicType *Symbolic +) +{ + Int n_row, n_col, nn, maxnrows, maxncols, nfr, ok, maxnrc, n1 ; + + n_row = Work->n_row ; + n_col = Work->n_col ; + nn = MAX (n_row, n_col) ; + nfr = Work->nfr ; + n1 = Symbolic->n1 ; + ASSERT (n1 <= n_row && n1 <= n_col) ; + + maxnrows = Symbolic->maxnrows + Symbolic->nb ; + maxnrows = MIN (n_row, maxnrows) ; + maxncols = Symbolic->maxncols + Symbolic->nb ; + maxncols = MIN (n_col, maxncols) ; + maxnrc = MAX (maxnrows, maxncols) ; + + DEBUG0 (("work alloc: maxnrows+nb "ID" maxncols+nb "ID"\n", + maxnrows, maxncols)) ; + + /* 15 allocations, freed in free_work: */ + /* accounted for in UMF_set_stats (work_usage) */ + Work->Wx = (Entry *) UMF_malloc (maxnrows + 1, sizeof (Entry)) ; + Work->Wy = (Entry *) UMF_malloc (maxnrows + 1, sizeof (Entry)) ; + Work->Frpos = (Int *) UMF_malloc (n_row + 1, sizeof (Int)) ; + Work->Lpattern = (Int *) UMF_malloc (n_row + 1, sizeof (Int)) ; + Work->Fcpos = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; + Work->Wp = (Int *) UMF_malloc (nn + 1, sizeof (Int)) ; + Work->Wrp = (Int *) UMF_malloc (MAX (n_col,maxnrows) + 1, sizeof (Int)) ; + Work->Frows = (Int *) UMF_malloc (maxnrows + 1, sizeof (Int)) ; + Work->Wm = (Int *) UMF_malloc (maxnrows + 1, sizeof (Int)) ; + Work->Fcols = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; + Work->Wio = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; + Work->Woi = (Int *) UMF_malloc (maxncols + 1, sizeof (Int)) ; + Work->Woo = (Int *) UMF_malloc (maxnrc + 1, sizeof (Int)); + Work->elen = (n_col - n1) + (n_row - n1) + MIN (n_col-n1, n_row-n1) + 1 ; + Work->E = (Int *) UMF_malloc (Work->elen, sizeof (Int)) ; + Work->Front_new1strow = (Int *) UMF_malloc (nfr + 1, sizeof (Int)) ; + + ok = (Work->Frpos && Work->Fcpos && Work->Lpattern + && Work->Wp && Work->Wrp && Work->Frows && Work->Fcols + && Work->Wio && Work->Woi && Work->Woo && Work->Wm + && Work->E && Work->Front_new1strow && Work->Wx && Work->Wy) ; + + /* 2 allocations: accounted for in UMF_set_stats (work_usage) */ + if (Symbolic->prefer_diagonal) + { + Work->Diagonal_map = (Int *) UMF_malloc (nn, sizeof (Int)) ; + Work->Diagonal_imap = (Int *) UMF_malloc (nn, sizeof (Int)) ; + ok = ok && Work->Diagonal_map && Work->Diagonal_imap ; + } + else + { + /* no diagonal map needed for rectangular matrices */ + Work->Diagonal_map = (Int *) NULL ; + Work->Diagonal_imap = (Int *) NULL ; + } + + /* 1 allocation, may become part of Numeric (if singular or rectangular): */ + Work->Upattern = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; + ok = ok && Work->Upattern ; + + /* current frontal matrix does not yet exist */ + Work->Flublock = (Entry *) NULL ; + Work->Flblock = (Entry *) NULL ; + Work->Fublock = (Entry *) NULL ; + Work->Fcblock = (Entry *) NULL ; + + DEBUG0 (("work alloc done.\n")) ; + return (ok) ; +} + + +/* ========================================================================== */ +/* === free_work ============================================================ */ +/* ========================================================================== */ + +PRIVATE void free_work +( + WorkType *Work +) +{ + DEBUG0 (("work free:\n")) ; + if (Work) + { + /* these 16 objects do exist */ + Work->Wx = (Entry *) UMF_free ((void *) Work->Wx) ; + Work->Wy = (Entry *) UMF_free ((void *) Work->Wy) ; + Work->Frpos = (Int *) UMF_free ((void *) Work->Frpos) ; + Work->Fcpos = (Int *) UMF_free ((void *) Work->Fcpos) ; + Work->Lpattern = (Int *) UMF_free ((void *) Work->Lpattern) ; + Work->Upattern = (Int *) UMF_free ((void *) Work->Upattern) ; + Work->Wp = (Int *) UMF_free ((void *) Work->Wp) ; + Work->Wrp = (Int *) UMF_free ((void *) Work->Wrp) ; + Work->Frows = (Int *) UMF_free ((void *) Work->Frows) ; + Work->Fcols = (Int *) UMF_free ((void *) Work->Fcols) ; + Work->Wio = (Int *) UMF_free ((void *) Work->Wio) ; + Work->Woi = (Int *) UMF_free ((void *) Work->Woi) ; + Work->Woo = (Int *) UMF_free ((void *) Work->Woo) ; + Work->Wm = (Int *) UMF_free ((void *) Work->Wm) ; + Work->E = (Int *) UMF_free ((void *) Work->E) ; + Work->Front_new1strow = + (Int *) UMF_free ((void *) Work->Front_new1strow) ; + + /* these objects might not exist */ + Work->Diagonal_map = (Int *) UMF_free ((void *) Work->Diagonal_map) ; + Work->Diagonal_imap = (Int *) UMF_free ((void *) Work->Diagonal_imap) ; + } + DEBUG0 (("work free done.\n")) ; +} + + +/* ========================================================================== */ +/* === error ================================================================ */ +/* ========================================================================== */ + +/* Error return from UMFPACK_numeric. Free all allocated memory. */ + +PRIVATE void error +( + NumericType **Numeric, + WorkType *Work +) +{ + free_work (Work) ; + UMFPACK_free_numeric ((void **) Numeric) ; + ASSERT (UMF_malloc_count == init_count) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_qsymbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_qsymbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_qsymbolic.c @@ -0,0 +1,2415 @@ +/* ========================================================================== */ +/* === UMFPACK_qsymbolic ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Performs a symbolic factorization. + See umfpack_qsymbolic.h and umfpack_symbolic.h for details. + + Dynamic memory usage: about (3.4nz + 8n + n) integers and n double's as + workspace (via UMF_malloc, for a square matrix). All of it is free'd via + UMF_free if an error occurs. If successful, the Symbolic object contains + 12 to 14 objects allocated by UMF_malloc, with a total size of no more + than about 13*n integers. +*/ + +#include "umf_internal.h" +#include "umf_symbolic_usage.h" +#include "umf_colamd.h" +#include "umf_set_stats.h" +#include "umf_analyze.h" +#include "umf_transpose.h" +#include "umf_is_permutation.h" +#include "umf_malloc.h" +#include "umf_free.h" +#include "umf_2by2.h" +#include "umf_singletons.h" + +typedef struct /* SWType */ +{ + Int *Front_npivcol ; /* size n_col + 1 */ + Int *Front_nrows ; /* size n_col */ + Int *Front_ncols ; /* size n_col */ + Int *Front_parent ; /* size n_col */ + Int *Front_cols ; /* size n_col */ + Int *InFront ; /* size n_row */ + Int *Ci ; /* size Clen */ + Int *Cperm1 ; /* size n_col */ + Int *Rperm1 ; /* size n_row */ + Int *InvRperm1 ; /* size n_row */ + Int *Si ; /* size nz */ + Int *Sp ; /* size n_col + 1 */ + double *Rs ; /* size n_row */ + Int *Rperm_2by2 ; /* size n_row */ + +} SWType ; + +PRIVATE void free_work +( + SWType *SW +) ; + +PRIVATE void error +( + SymbolicType **Symbolic, + SWType *SW +) ; + +/* worst-case usage for SW object */ +#define SYM_WORK_USAGE(n_col,n_row,Clen) \ + (DUNITS (Int, Clen) + \ + DUNITS (Int, nz) + \ + 4 * DUNITS (Int, n_row) + \ + 4 * DUNITS (Int, n_col) + \ + 2 * DUNITS (Int, n_col + 1) + \ + DUNITS (double, n_row)) + +/* required size of Ci for code that calls UMF_transpose and UMF_analyze below*/ +#define UMF_ANALYZE_CLEN(nz,n_row,n_col,nn) \ + ((n_col) + MAX ((nz),(n_col)) + 3*(nn)+1 + (n_col)) + +/* size of an element (in Units), including tuples */ +#define ELEMENT_SIZE(r,c) \ + (DGET_ELEMENT_SIZE (r, c) + 1 + (r + c) * UNITS (Tuple, 1)) + +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif + +/* ========================================================================== */ +/* === do_amd =============================================================== */ +/* ========================================================================== */ + +PRIVATE void do_amd +( + Int n, + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + Int Q [ ], /* output permutation, j = Q [k] */ + Int Qinv [ ], /* output inverse permutation, Qinv [j] = k */ + Int Sdeg [ ], /* degree of A+A', from AMD_aat */ + Int Clen, /* size of Ci */ + Int Ci [ ], /* size Ci workspace */ + double amd_Control [ ], /* AMD control parameters */ + double amd_Info [ ], /* AMD info */ + SymbolicType *Symbolic, /* Symbolic object */ + double Info [ ] /* UMFPACK info */ +) +{ + + if (n == 0) + { + Symbolic->amd_dmax = 0 ; + Symbolic->amd_lunz = 0 ; + Info [UMFPACK_SYMMETRIC_LUNZ] = 0 ; + Info [UMFPACK_SYMMETRIC_FLOPS] = 0 ; + Info [UMFPACK_SYMMETRIC_DMAX] = 0 ; + Info [UMFPACK_SYMMETRIC_NDENSE] = 0 ; + } + else + { + AMD_1 (n, Ap, Ai, Q, Qinv, Sdeg, Clen, Ci, amd_Control, amd_Info) ; + + /* return estimates computed from AMD on PA+PA' */ + Symbolic->amd_dmax = amd_Info [AMD_DMAX] ; + Symbolic->amd_lunz = 2 * amd_Info [AMD_LNZ] + n ; + Info [UMFPACK_SYMMETRIC_LUNZ] = Symbolic->amd_lunz ; + Info [UMFPACK_SYMMETRIC_FLOPS] = DIV_FLOPS * amd_Info [AMD_NDIV] + + MULTSUB_FLOPS * amd_Info [AMD_NMULTSUBS_LU] ; + Info [UMFPACK_SYMMETRIC_DMAX] = Symbolic->amd_dmax ; + Info [UMFPACK_SYMMETRIC_NDENSE] = amd_Info [AMD_NDENSE] ; + Info [UMFPACK_SYMBOLIC_DEFRAG] += amd_Info [AMD_NCMPA] ; + } +} + +/* ========================================================================== */ +/* === prune_singletons ===================================================== */ +/* ========================================================================== */ + +/* Create the submatrix after removing the n1 singletons. The matrix has + * row and column indices in the range 0 to n_row-n1 and 0 to n_col-n1, + * respectively. */ + +PRIVATE Int prune_singletons +( + Int n1, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + Int Cperm1 [ ], + Int InvRperm1 [ ], + Int Si [ ], + Int Sp [ ] +#ifndef NDEBUG + , Int Rperm1 [ ] + , Int n_row +#endif +) +{ + Int row, k, pp, p, oldcol, newcol, newrow, nzdiag, do_nzdiag ; +#ifdef COMPLEX + Int split = SPLIT (Az) ; +#endif + + nzdiag = 0 ; + do_nzdiag = (Ax != (double *) NULL) ; + +#ifndef NDEBUG + DEBUGm4 (("Prune : S = A (Cperm1 (n1+1:end), Rperm1 (n1+1:end))\n")) ; + for (k = 0 ; k < n_row ; k++) + { + ASSERT (Rperm1 [k] >= 0 && Rperm1 [k] < n_row) ; + ASSERT (InvRperm1 [Rperm1 [k]] == k) ; + } +#endif + + /* create the submatrix after removing singletons */ + + pp = 0 ; + for (k = n1 ; k < n_col ; k++) + { + oldcol = Cperm1 [k] ; + newcol = k - n1 ; + DEBUG5 (("Prune singletons k "ID" oldcol "ID" newcol "ID": "ID"\n", + k, oldcol, newcol, pp)) ; + Sp [newcol] = pp ; /* load column pointers */ + for (p = Ap [oldcol] ; p < Ap [oldcol+1] ; p++) + { + row = Ai [p] ; + DEBUG5 ((" "ID": row "ID, pp, row)) ; + ASSERT (row >= 0 && row < n_row) ; + newrow = InvRperm1 [row] - n1 ; + ASSERT (newrow < n_row - n1) ; + if (newrow >= 0) + { + DEBUG5 ((" newrow "ID, newrow)) ; + Si [pp++] = newrow ; + if (do_nzdiag) + { + /* count the number of truly nonzero entries on the + * diagonal of S, excluding entries that are present, + * but numerically zero */ + if (newrow == newcol) + { + /* this is the diagonal entry */ +#ifdef COMPLEX + if (split) + { + if (SCALAR_IS_NONZERO (Ax [p]) || + SCALAR_IS_NONZERO (Az [p])) + { + nzdiag++ ; + } + } + else + { + if (SCALAR_IS_NONZERO (Ax [2*p ]) || + SCALAR_IS_NONZERO (Ax [2*p+1])) + { + nzdiag++ ; + } + } +#else + if (SCALAR_IS_NONZERO (Ax [p])) + { + nzdiag++ ; + } +#endif + } + } + } + DEBUG5 (("\n")) ; + } + } + Sp [n_col - n1] = pp ; + + return (nzdiag) ; +} + +/* ========================================================================== */ +/* === combine_ordering ===================================================== */ +/* ========================================================================== */ + +PRIVATE void combine_ordering +( + Int n1, + Int nempty_col, + Int n_col, + Int Cperm_init [ ], /* output permutation */ + Int Cperm1 [ ], /* singleton and empty column ordering */ + Int Qinv [ ] /* Qinv from AMD or COLAMD */ +) +{ + Int k, oldcol, newcol, knew ; + + /* combine the singleton ordering with Qinv */ +#ifndef NDEBUG + for (k = 0 ; k < n_col ; k++) + { + Cperm_init [k] = EMPTY ; + } +#endif + for (k = 0 ; k < n1 ; k++) + { + DEBUG1 ((ID" Initial singleton: "ID"\n", k, Cperm1 [k])) ; + Cperm_init [k] = Cperm1 [k] ; + } + for (k = n1 ; k < n_col - nempty_col ; k++) + { + /* this is a non-singleton column */ + oldcol = Cperm1 [k] ; /* user's name for this column */ + newcol = k - n1 ; /* Qinv's name for this column */ + knew = Qinv [newcol] ; /* Qinv's ordering for this column */ + knew += n1 ; /* shift order, after singletons */ + DEBUG1 ((" k "ID" oldcol "ID" newcol "ID" knew "ID"\n", + k, oldcol, newcol, knew)) ; + ASSERT (knew >= 0 && knew < n_col - nempty_col) ; + ASSERT (Cperm_init [knew] == EMPTY) ; + Cperm_init [knew] = oldcol ; + } + for (k = n_col - nempty_col ; k < n_col ; k++) + { + Cperm_init [k] = Cperm1 [k] ; + } +#ifndef NDEBUG + { + Int *W = (Int *) malloc ((n_col + 1) * sizeof (Int)) ; + ASSERT (UMF_is_permutation (Cperm_init, W, n_col, n_col)) ; + free (W) ; + } +#endif + +} + +/* ========================================================================== */ +/* === UMFPACK_qsymbolic ==================================================== */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_qsymbolic +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + const Int Quser [ ], + void **SymbolicHandle, + const double Control [UMFPACK_CONTROL], + double User_Info [UMFPACK_INFO] +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double knobs [COLAMD_KNOBS], flops, f, r, c, force_fixQ, + Info2 [UMFPACK_INFO], drow, dcol, dtail_usage, dlf, duf, dmax_usage, + dhead_usage, dlnz, dunz, dmaxfrsize, dClen, dClen_analyze, sym, + amd_Info [AMD_INFO], dClen_amd, dr, dc, cr, cc, cp, + amd_Control [AMD_CONTROL], stats [2], tol ; + double *Info ; + Int i, nz, j, newj, status, f1, f2, maxnrows, maxncols, nfr, col, + nchains, maxrows, maxcols, p, nb, nn, *Chain_start, *Chain_maxrows, + *Chain_maxcols, *Front_npivcol, *Ci, Clen, colamd_stats [COLAMD_STATS], + fpiv, n_inner, child, parent, *Link, row, *Front_parent, + analyze_compactions, k, chain, is_sym, *Si, *Sp, n2, do_UMF_analyze, + fpivcol, fallrows, fallcols, *InFront, *F1, snz, *Front_1strow, f1rows, + kk, *Cperm_init, *Rperm_init, newrow, *InvRperm1, *Front_leftmostdesc, + Clen_analyze, strategy, Clen_amd, fixQ, prefer_diagonal, nzdiag, nzaat, + *Wq, *Sdeg, *Fr_npivcol, nempty, *Fr_nrows, *Fr_ncols, *Fr_parent, + *Fr_cols, nempty_row, nempty_col, user_auto_strategy, fail, max_rdeg, + head_usage, tail_usage, lnz, unz, esize, *Esize, rdeg, *Cdeg, *Rdeg, + *Cperm1, *Rperm1, n1, oldcol, newcol, n1c, n1r, *Rperm_2by2, oldrow, + dense_row_threshold, tlen, aggressive, scale, *Rp, *Ri ; + + SymbolicType *Symbolic ; + SWType SWspace, *SW ; + +#ifndef NDEBUG + UMF_dump_start ( ) ; + init_count = UMF_malloc_count ; + PRINTF (( +"**** Debugging enabled (UMFPACK will be exceedingly slow!) *****************\n" + )) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get the amount of time used by the process so far */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (stats) ; + + /* ---------------------------------------------------------------------- */ + /* get control settings and check input parameters */ + /* ---------------------------------------------------------------------- */ + + drow = GET_CONTROL (UMFPACK_DENSE_ROW, UMFPACK_DEFAULT_DENSE_ROW) ; + dcol = GET_CONTROL (UMFPACK_DENSE_COL, UMFPACK_DEFAULT_DENSE_COL) ; + nb = GET_CONTROL (UMFPACK_BLOCK_SIZE, UMFPACK_DEFAULT_BLOCK_SIZE) ; + strategy = GET_CONTROL (UMFPACK_STRATEGY, UMFPACK_DEFAULT_STRATEGY) ; + tol = GET_CONTROL (UMFPACK_2BY2_TOLERANCE, UMFPACK_DEFAULT_2BY2_TOLERANCE) ; + scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ; + force_fixQ = GET_CONTROL (UMFPACK_FIXQ, UMFPACK_DEFAULT_FIXQ) ; + AMD_defaults (amd_Control) ; + amd_Control [AMD_DENSE] = + GET_CONTROL (UMFPACK_AMD_DENSE, UMFPACK_DEFAULT_AMD_DENSE) ; + aggressive = + (GET_CONTROL (UMFPACK_AGGRESSIVE, UMFPACK_DEFAULT_AGGRESSIVE) != 0) ; + amd_Control [AMD_AGGRESSIVE] = aggressive ; + + nb = MAX (2, nb) ; + nb = MIN (nb, MAXNB) ; + ASSERT (nb >= 0) ; + if (nb % 2 == 1) nb++ ; /* make sure nb is even */ + DEBUG0 (("UMFPACK_qsymbolic: nb = "ID" aggressive = "ID"\n", nb, + aggressive)) ; + + tol = MAX (0.0, MIN (tol, 1.0)) ; + if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX) + { + scale = UMFPACK_DEFAULT_SCALE ; + } + + if (User_Info != (double *) NULL) + { + /* return Info in user's array */ + Info = User_Info ; + } + else + { + /* no Info array passed - use local one instead */ + Info = Info2 ; + } + /* clear all of Info */ + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + Info [i] = EMPTY ; + } + + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + + Info [UMFPACK_STATUS] = UMFPACK_OK ; + Info [UMFPACK_NROW] = n_row ; + Info [UMFPACK_NCOL] = n_col ; + Info [UMFPACK_SIZE_OF_UNIT] = (double) (sizeof (Unit)) ; + Info [UMFPACK_SIZE_OF_INT] = (double) (sizeof (int)) ; + Info [UMFPACK_SIZE_OF_LONG] = (double) (sizeof (long)) ; + Info [UMFPACK_SIZE_OF_POINTER] = (double) (sizeof (void *)) ; + Info [UMFPACK_SIZE_OF_ENTRY] = (double) (sizeof (Entry)) ; + Info [UMFPACK_SYMBOLIC_DEFRAG] = 0 ; + + if (!Ai || !Ap || !SymbolicHandle) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; + return (UMFPACK_ERROR_argument_missing) ; + } + + *SymbolicHandle = (void *) NULL ; + + if (n_row <= 0 || n_col <= 0) /* n_row, n_col must be > 0 */ + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_n_nonpositive ; + return (UMFPACK_ERROR_n_nonpositive) ; + } + + nz = Ap [n_col] ; + DEBUG0 (("n_row "ID" n_col "ID" nz "ID"\n", n_row, n_col, nz)) ; + Info [UMFPACK_NZ] = nz ; + if (nz < 0) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_matrix ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + + /* ---------------------------------------------------------------------- */ + /* get the requested strategy */ + /* ---------------------------------------------------------------------- */ + + if (n_row != n_col) + { + /* if the matrix is rectangular, the only available strategy is + * unsymmetric */ + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + DEBUGm3 (("Rectangular: forcing unsymmetric strategy\n")) ; + } + + if (strategy < UMFPACK_STRATEGY_AUTO + || strategy > UMFPACK_STRATEGY_SYMMETRIC) + { + /* unrecognized strategy */ + strategy = UMFPACK_STRATEGY_AUTO ; + } + + if (Quser != (Int *) NULL) + { + /* when the user provides Q, only symmetric and unsymmetric strategies + * are available */ + if (strategy == UMFPACK_STRATEGY_2BY2) + { + strategy = UMFPACK_STRATEGY_SYMMETRIC ; + } + if (strategy != UMFPACK_STRATEGY_SYMMETRIC) + { + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + } + } + + user_auto_strategy = (strategy == UMFPACK_STRATEGY_AUTO) ; + + /* ---------------------------------------------------------------------- */ + /* determine amount of memory required for UMFPACK_symbolic */ + /* ---------------------------------------------------------------------- */ + + /* The size of Clen required for UMF_colamd is always larger than */ + /* UMF_analyze, but the max is included here in case that changes in */ + /* future versions. */ + + /* This is about 2.2*nz + 9*n_col + 6*n_row, or nz/5 + 13*n_col + 6*n_row, + * whichever is bigger. For square matrices, it works out to + * 2.2nz + 15n, or nz/5 + 19n, whichever is bigger (typically 2.2nz+15n). */ + dClen = UMF_COLAMD_RECOMMENDED ((double) nz, (double) n_row, + (double) n_col) ; + + /* This is defined above, as max (nz,n_col) + 3*nn+1 + 2*n_col, where + * nn = max (n_row,n_col). It is always smaller than the space required + * for colamd or amd. */ + dClen_analyze = UMF_ANALYZE_CLEN ((double) nz, (double) n_row, + (double) n_col, (double) nn) ; + dClen = MAX (dClen, dClen_analyze) ; + + /* The space for AMD can be larger than what's required for colamd: */ + dClen_amd = 2.4 * (double) nz + 8 * (double) n_inner ; + /* additional space for the 2-by-2 strategy */ + dClen_amd += (double) MAX (nn, nz) ; + dClen = MAX (dClen, dClen_amd) ; + + /* worst case total memory usage for UMFPACK_symbolic (revised below) */ + Info [UMFPACK_SYMBOLIC_PEAK_MEMORY] = + SYM_WORK_USAGE (n_col, n_row, dClen) + + UMF_symbolic_usage (n_row, n_col, n_col, n_col, n_col, TRUE) ; + + if (INT_OVERFLOW (dClen * sizeof (Int))) + { + /* :: int overflow, Clen too large :: */ + /* Problem is too large for array indexing (Ci [i]) with an Int i. */ + /* Cannot even analyze the problem to determine upper bounds on */ + /* memory usage. Need to use the long integer version, umfpack_*l_*. */ + DEBUGm4 (("out of memory: symbolic int overflow\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + /* repeat the size calculations, in integers */ + Clen = UMF_COLAMD_RECOMMENDED (nz, n_row, n_col) ; + Clen_analyze = UMF_ANALYZE_CLEN (nz, n_row, n_col, nn) ; + Clen = MAX (Clen, Clen_analyze) ; + Clen_amd = 2.4 * nz + 8 * n_inner ; + Clen_amd += MAX (nn, nz) ; /* for Ri, in UMF_2by2 */ + Clen = MAX (Clen, Clen_amd) ; + + /* ---------------------------------------------------------------------- */ + /* allocate the first part of the Symbolic object (header and Cperm_init) */ + /* ---------------------------------------------------------------------- */ + + /* (1) Five calls to UMF_malloc are made, for a total space of + * 2 * (n_row + n_col) + 4 integers + sizeof (SymbolicType). + * sizeof (SymbolicType) is a small constant. This space is part of the + * Symbolic object and is not freed unless an error occurs. If A is square + * then this is about 4*n integers. + */ + + Symbolic = (SymbolicType *) UMF_malloc (1, sizeof (SymbolicType)) ; + + if (!Symbolic) + { + /* If we fail here, Symbolic is NULL and thus it won't be */ + /* dereferenced by UMFPACK_free_symbolic, as called by error ( ). */ + DEBUGm4 (("out of memory: symbolic object\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, (SWType *) NULL) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + /* We now know that Symbolic has been allocated */ + Symbolic->valid = 0 ; + Symbolic->Chain_start = (Int *) NULL ; + Symbolic->Chain_maxrows = (Int *) NULL ; + Symbolic->Chain_maxcols = (Int *) NULL ; + Symbolic->Front_npivcol = (Int *) NULL ; + Symbolic->Front_parent = (Int *) NULL ; + Symbolic->Front_1strow = (Int *) NULL ; + Symbolic->Front_leftmostdesc = (Int *) NULL ; + Symbolic->Esize = (Int *) NULL ; + Symbolic->esize = 0 ; + + Symbolic->Cperm_init = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Symbolic->Rperm_init = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + Symbolic->Cdeg = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Symbolic->Rdeg = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + Symbolic->Diagonal_map = (Int *) NULL ; + + Cperm_init = Symbolic->Cperm_init ; + Rperm_init = Symbolic->Rperm_init ; + Cdeg = Symbolic->Cdeg ; + Rdeg = Symbolic->Rdeg ; + + if (!Cperm_init || !Rperm_init || !Cdeg || !Rdeg) + { + DEBUGm4 (("out of memory: symbolic perm\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, (SWType *) NULL) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + Symbolic->n_row = n_row ; + Symbolic->n_col = n_col ; + Symbolic->nz = nz ; + Symbolic->nb = nb ; + + /* ---------------------------------------------------------------------- */ + /* check user's input permutation */ + /* ---------------------------------------------------------------------- */ + + if (Quser != (Int *) NULL) + { + /* use Cperm_init as workspace to check input permutation */ + if (!UMF_is_permutation (Quser, Cperm_init, n_col, n_col)) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_permutation ; + error (&Symbolic, (SWType *) NULL) ; + return (UMFPACK_ERROR_invalid_permutation) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* allocate workspace */ + /* ---------------------------------------------------------------------- */ + + /* (2) Eleven calls to UMF_malloc are made, for workspace of size + * Clen + nz + 7*n_col + 2*n_row + 2 integers. Clen is the larger of + * MAX (2*nz, 4*n_col) + 8*n_col + 6*n_row + n_col + nz/5 and + * 2.4*nz + 8 * MIN (n_row, n_col) + MAX (n_row, n_col, nz) + * If A is square and non-singular, then Clen is + * MAX (MAX (2*nz, 4*n) + 7*n + nz/5, 3.4*nz) + 8*n + * If A has at least 4*n nonzeros then Clen is + * MAX (2.2*nz + 7*n, 3.4*nz) + 8*n + * If A has at least (7/1.2)*n nonzeros, (about 5.8*n), then Clen is + * 3.4*nz + 8*n + * This space will be free'd when this routine finishes. + * + * Total space thus far is about 3.4nz + 12n integers. + * For the double precision, 32-bit integer version, the user's matrix + * requires an equivalent space of 3*nz + n integers. So this space is just + * slightly larger than the user's input matrix (including the numerical + * values themselves). + */ + + SW = &SWspace ; /* used for UMFPACK_symbolic only */ + + /* Note that SW->Front_* does not include the dummy placeholder front. */ + /* This space is accounted for by the SYM_WORK_USAGE macro. */ + + /* this is free'd early */ + SW->Si = (Int *) UMF_malloc (nz, sizeof (Int)) ; + SW->Sp = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; + SW->InvRperm1 = (Int *) UMF_malloc (n_row, sizeof (Int)) ; + SW->Cperm1 = (Int *) UMF_malloc (n_col, sizeof (Int)) ; + + /* this is free'd late */ + SW->Ci = (Int *) UMF_malloc (Clen, sizeof (Int)) ; + SW->Front_npivcol = (Int *) UMF_malloc (n_col + 1, sizeof (Int)) ; + SW->Front_nrows = (Int *) UMF_malloc (n_col, sizeof (Int)) ; + SW->Front_ncols = (Int *) UMF_malloc (n_col, sizeof (Int)) ; + SW->Front_parent = (Int *) UMF_malloc (n_col, sizeof (Int)) ; + SW->Front_cols = (Int *) UMF_malloc (n_col, sizeof (Int)) ; + SW->Rperm1 = (Int *) UMF_malloc (n_row, sizeof (Int)) ; + SW->InFront = (Int *) UMF_malloc (n_row, sizeof (Int)) ; + + /* this is allocated later, and free'd after Cperm1 but before Ci */ + SW->Rperm_2by2 = (Int *) NULL ; /* will be nn Int's */ + + /* this is allocated last, and free'd first */ + SW->Rs = (double *) NULL ; /* will be n_row double's */ + + Ci = SW->Ci ; + Fr_npivcol = SW->Front_npivcol ; + Fr_nrows = SW->Front_nrows ; + Fr_ncols = SW->Front_ncols ; + Fr_parent = SW->Front_parent ; + Fr_cols = SW->Front_cols ; + Cperm1 = SW->Cperm1 ; + Rperm1 = SW->Rperm1 ; + Si = SW->Si ; + Sp = SW->Sp ; + InvRperm1 = SW->InvRperm1 ; + Rperm_2by2 = (Int *) NULL ; + InFront = SW->InFront ; + + if (!Ci || !Fr_npivcol || !Fr_nrows || !Fr_ncols || !Fr_parent || !Fr_cols + || !Cperm1 || !Rperm1 || !Si || !Sp || !InvRperm1 || !InFront) + { + DEBUGm4 (("out of memory: symbolic work\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + DEBUG0 (("Symbolic UMF_malloc_count - init_count = "ID"\n", + UMF_malloc_count - init_count)) ; + ASSERT (UMF_malloc_count == init_count + 17) ; + + /* ---------------------------------------------------------------------- */ + /* find the row and column singletons */ + /* ---------------------------------------------------------------------- */ + + /* [ use first nz + n_row + MAX (n_row, n_col) entries in Ci as workspace, + * and use Rperm_init as workspace */ + ASSERT (Clen >= nz + n_row + MAX (n_row, n_col)) ; + + status = UMF_singletons (n_row, n_col, Ap, Ai, Quser, strategy, + Cdeg, Cperm1, Rdeg, + Rperm1, InvRperm1, &n1, &n1c, &n1r, &nempty_col, &nempty_row, &is_sym, + &max_rdeg, /* workspace: */ Rperm_init, Ci, Ci + nz, Ci + nz + n_row) ; + + /* ] done using Rperm_init and Ci as workspace */ + + /* InvRperm1 is now the inverse of Rperm1 */ + + if (status != UMFPACK_OK) + { + DEBUGm4 (("matrix invalid: UMF_singletons\n")) ; + Info [UMFPACK_STATUS] = status ; + error (&Symbolic, SW) ; + return (status) ; + } + Info [UMFPACK_NEMPTY_COL] = nempty_col ; + Info [UMFPACK_NEMPTY_ROW] = nempty_row ; + Info [UMFPACK_NDENSE_COL] = 0 ; /* # dense rows/cols recomputed below */ + Info [UMFPACK_NDENSE_ROW] = 0 ; + Info [UMFPACK_COL_SINGLETONS] = n1c ; + Info [UMFPACK_ROW_SINGLETONS] = n1r ; + Info [UMFPACK_S_SYMMETRIC] = is_sym ; + + nempty = MIN (nempty_col, nempty_row) ; + Symbolic->nempty_row = nempty_row ; + Symbolic->nempty_col = nempty_col ; + + /* UMF_singletons has verified that the user's input matrix is valid */ + ASSERT (AMD_valid (n_row, n_col, Ap, Ai)) ; + + Symbolic->n1 = n1 ; + Symbolic->nempty = nempty ; + ASSERT (n1 <= n_inner) ; + n2 = nn - n1 - nempty ; + + dense_row_threshold = + UMFPACK_DENSE_DEGREE_THRESHOLD (drow, n_col - n1 - nempty_col) ; + Symbolic->dense_row_threshold = dense_row_threshold ; + + if (!is_sym) + { + /* either the pruned submatrix rectangular, or it is square and + * Rperm [n1 .. n-nempty-1] is not the same as Cperm [n1 .. n-nempty-1]. + * Switch to the unsymmetric strategy, ignoring user-requested + * strategy. */ + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + DEBUGm4 (("Strategy: Unsymmetric singletons\n")) ; + } + + /* ---------------------------------------------------------------------- */ + /* determine symmetry, nzdiag, and degrees of S+S' */ + /* ---------------------------------------------------------------------- */ + + /* S is the matrix obtained after removing singletons + * = A (Cperm1 [n1..n_col-nempty_col-1], Rperm1 [n1..n_row-nempty_row-1]) + */ + + Wq = Rperm_init ; /* use Rperm_init as workspace for Wq [ */ + Sdeg = Cperm_init ; /* use Cperm_init as workspace for Sdeg [ */ + sym = EMPTY ; + nzaat = EMPTY ; + nzdiag = EMPTY ; + for (i = 0 ; i < AMD_INFO ; i++) + { + amd_Info [i] = EMPTY ; + } + + if (strategy != UMFPACK_STRATEGY_UNSYMMETRIC) + { + /* This also determines the degree of each node in S+S' (Sdeg), which + * is needed by the 2-by-2 strategy, the symmetry of S, and the number + * of nonzeros on the diagonal of S. */ + ASSERT (n_row == n_col) ; + ASSERT (nempty_row == nempty_col) ; + + /* get the count of nonzeros on the diagonal of S, excluding explicitly + * zero entries. nzdiag = amd_Info [AMD_NZDIAG] counts the zero entries + * in S. */ + + nzdiag = prune_singletons (n1, nn, Ap, Ai, Ax, +#ifdef COMPLEX + Az, +#endif + Cperm1, InvRperm1, Si, Sp +#ifndef NDEBUG + , Rperm1, nn +#endif + ) ; + + /* use Ci as workspace to sort S into R, if needed [ */ + if (Quser != (Int *) NULL) + { + /* need to sort the columns of S first */ + Rp = Ci ; + Ri = Ci + (n_row) + 1 ; + (void) UMF_transpose (n2, n2, Sp, Si, (double *) NULL, + (Int *) NULL, (Int *) NULL, 0, + Rp, Ri, (double *) NULL, Wq, FALSE +#ifdef COMPLEX + , (double *) NULL, (double *) NULL, FALSE +#endif + ) ; + } + else + { + /* S already has sorted columns */ + Rp = Sp ; + Ri = Si ; + } + ASSERT (AMD_valid (n2, n2, Rp, Ri)) ; + + nzaat = AMD_aat (n2, Rp, Ri, Sdeg, Wq, amd_Info) ; + sym = amd_Info [AMD_SYMMETRY] ; + Info [UMFPACK_N2] = n2 ; + /* nzdiag = amd_Info [AMD_NZDIAG] counts the zero entries of S too */ + + /* done using Ci as workspace to sort S into R ] */ + +#ifndef NDEBUG + for (k = 0 ; k < n2 ; k++) + { + ASSERT (Sdeg [k] >= 0 && Sdeg [k] < n2) ; + } + ASSERT (Sp [n2] - n2 <= nzaat && nzaat <= 2 * Sp [n2]) ; + DEBUG0 (("Explicit zeros: "ID" %g\n", nzdiag, amd_Info [AMD_NZDIAG])) ; +#endif + + } + + /* get statistics from amd_aat, if computed */ + Symbolic->sym = sym ; + Symbolic->nzaat = nzaat ; + Symbolic->nzdiag = nzdiag ; + Symbolic->amd_dmax = EMPTY ; + + Info [UMFPACK_PATTERN_SYMMETRY] = sym ; + Info [UMFPACK_NZ_A_PLUS_AT] = nzaat ; + Info [UMFPACK_NZDIAG] = nzdiag ; + + /* ---------------------------------------------------------------------- */ + /* determine the initial strategy based on symmetry and nnz (diag (S)) */ + /* ---------------------------------------------------------------------- */ + + if (strategy == UMFPACK_STRATEGY_AUTO) + { + if (sym < 0.10) + { + /* highly unsymmetric: use the unsymmetric strategy */ + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + DEBUGm4 (("Strategy: select unsymmetric\n")) ; + } + else if (sym >= 0.7 && nzdiag == n2) + { + /* mostly symmetric, zero-free diagonal: use symmetric strategy */ + strategy = UMFPACK_STRATEGY_SYMMETRIC ; + DEBUGm4 (("Strategy: select symmetric\n")) ; + } + else + { + /* Evaluate the symmetric 2-by-2 strategy, and select it, or + * the unsymmetric strategy if the 2-by-2 strategy doesn't look + * promising. */ + strategy = UMFPACK_STRATEGY_2BY2 ; + DEBUGm4 (("Strategy: try 2-by-2\n")) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* try the 2-by-2 strategy */ + /* ---------------------------------------------------------------------- */ + + /* (3) If the 2-by-2 strategy is attempted, additional workspace of size + * nn integers and nn double's is allocated, where nn = n_row = n_col. + * The real workspace is immediately free'd. The integer workspace of + * size nn remains until the end of umfpack_qsymbolic. */ + + /* If the resulting matrix S (Rperm_2by2, :) is too unsymmetric, then the + * unsymmetric strategy will be used instead. */ + + if (strategy == UMFPACK_STRATEGY_2BY2) + { + double sym2 ; + Int *Blen, *W, nz_papat, nzd2, nweak, unmatched, Clen3 ; + + /* ------------------------------------------------------------------ */ + /* get workspace for UMF_2by2 */ + /* ------------------------------------------------------------------ */ + + ASSERT (n_row == n_col && nn == n_row) ; + +#ifndef NDEBUG + for (k = 0 ; k < n2 ; k++) + { + ASSERT (Sdeg [k] >= 0 && Sdeg [k] < n2) ; + } +#endif + + /* allocate Rperm_2by2 */ + SW->Rperm_2by2 = (Int *) UMF_malloc (nn, sizeof (Int)) ; + Rperm_2by2 = SW->Rperm_2by2 ; + if (Rperm_2by2 == (Int *) NULL) + { + DEBUGm4 (("out of memory: Rperm_2by2\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + /* allocate Ri from the tail end of Ci [ */ + Clen3 = Clen - (MAX (nn, nz) + 1) ; + Ri = Ci + Clen3 ; + ASSERT (Clen3 >= nz) ; /* space required for UMF_2by2 */ + + /* use Fr_* as workspace for Rp, Blen, and W [ */ + Rp = Fr_npivcol ; + Blen = Fr_ncols ; + W = Fr_cols ; + + if (scale != UMFPACK_SCALE_NONE) + { + SW->Rs = (double *) UMF_malloc (nn, sizeof (double)) ; + if (SW->Rs == (double *) NULL) + { + DEBUGm4 (("out of memory: scale factors for 2-by-2\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + } + + /* ------------------------------------------------------------------ */ + /* find the 2-by-2 row permutation */ + /* ------------------------------------------------------------------ */ + + /* find a row permutation Rperm_2by2 such that S (Rperm_2by2, :) + * has a healthy diagonal */ + + UMF_2by2 (nn, Ap, Ai, Ax, +#ifdef COMPLEX + Az, +#endif + tol, scale, Cperm1, +#ifndef NDEBUG + Rperm1, +#endif + InvRperm1, n1, nempty, Sdeg, Rperm_2by2, &nweak, &unmatched, + Ri, Rp, SW->Rs, Blen, W, Ci, Wq) ; + DEBUGm3 (("2by2: nweak "ID" unmatched "ID"\n", nweak, unmatched)) ; + Info [UMFPACK_2BY2_NWEAK] = nweak ; + Info [UMFPACK_2BY2_UNMATCHED] = unmatched ; + + SW->Rs = (double *) UMF_free ((void *) SW->Rs) ; + + /* R = S (Rperm_2by2,:)' */ + (void) UMF_transpose (n2, n2, Sp, Si, (double *) NULL, Rperm_2by2, + (Int *) NULL, 0, Rp, Ri, (double *) NULL, W, FALSE +#ifdef COMPLEX + , (double *) NULL, (double *) NULL, FALSE +#endif + ) ; + ASSERT (AMD_valid (n2, n2, Rp, Ri)) ; + + /* contents of Si and Sp no longer needed, but the space is + * still needed */ + + /* ------------------------------------------------------------------ */ + /* find symmetry of S (Rperm_2by2, :)', and prepare to order with AMD */ + /* ------------------------------------------------------------------ */ + + for (i = 0 ; i < AMD_INFO ; i++) + { + amd_Info [i] = EMPTY ; + } + nz_papat = AMD_aat (n2, Rp, Ri, Sdeg, Wq, amd_Info) ; + sym2 = amd_Info [AMD_SYMMETRY] ; + nzd2 = amd_Info [AMD_NZDIAG] ; + + Info [UMFPACK_2BY2_PATTERN_SYMMETRY] = sym2 ; + Info [UMFPACK_2BY2_NZ_PA_PLUS_PAT] = nz_papat ; + Info [UMFPACK_2BY2_NZDIAG] = nzd2 ; + + DEBUG0 (("2by2: sym2 %g nzd2 "ID" n2 "ID"\n", sym2, nzd2, n2)) ; + + /* ------------------------------------------------------------------ */ + /* evaluate the 2-by-2 results */ + /* ------------------------------------------------------------------ */ + + if (user_auto_strategy) + { + if ((sym2 > 1.1 * sym) && (nzd2 > 0.9 * n2)) + { + /* 2-by-2 made it much more symmetric */ + DEBUGm4 (("eval Strategy 2by2: much more symmetric: 2by2\n")) ; + strategy = UMFPACK_STRATEGY_2BY2 ; + } + else if (sym2 < 0.7 * sym) + { + /* 2-by-2 made it much more unsymmetric */ + DEBUGm4 (("eval Strategy 2by2: much more UNsymmetric:unsym\n")); + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + } + else if (sym2 < 0.25) + { + DEBUGm4 (("eval Strategy 2by2: is UNsymmetric: unsym\n")); + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + } + else if (sym2 >= 0.51) + { + DEBUGm4 (("eval Strategy 2by2: sym2 >= 0.51: 2by2\n")) ; + strategy = UMFPACK_STRATEGY_2BY2 ; + } + else if (sym2 >= 0.999 * sym) + { + /* 2-by-2 improved symmetry, or made it only slightly worse */ + DEBUGm4 (("eval Strategy 2by2: sym2 >= 0.999 sym: 2by2\n")) ; + strategy = UMFPACK_STRATEGY_2BY2 ; + } + else + { + /* can't decide what to do, so pick the unsymmetric strategy */ + DEBUGm4 (("eval Strategy 2by2: punt: unsym\n")); + strategy = UMFPACK_STRATEGY_UNSYMMETRIC ; + } + } + + /* ------------------------------------------------------------------ */ + /* if the 2-by-2 strategy is selected: */ + /* ------------------------------------------------------------------ */ + + if (strategy == UMFPACK_STRATEGY_2BY2) + { + if (Quser == (Int *) NULL) + { + /* 2-by-2 strategy is successful */ + /* compute amd (S) */ + Int *Qinv = Fr_npivcol ; + ASSERT (Clen3 >= (nz_papat + nz_papat/5 + nn) + 7*nn) ; + do_amd (n2, Rp, Ri, Wq, Qinv, Sdeg, Clen3, Ci, + amd_Control, amd_Info, Symbolic, Info) ; + /* combine the singleton ordering and the AMD ordering */ + combine_ordering (n1, nempty, nn, Cperm_init, Cperm1, Qinv) ; + } + /* fix Rperm_2by2 to reflect A, not S */ + for (k = 0 ; k < n1 ; k++) + { + oldcol = Cperm1 [k] ; + i = k ; + oldrow = Rperm1 [k] ; + W [oldcol] = oldrow ; + } + for (k = n1 ; k < nn - nempty ; k++) + { + oldcol = Cperm1 [k] ; + i = Rperm_2by2 [k - n1] + n1 ; + oldrow = Rperm1 [i] ; + W [oldcol] = oldrow ; + } + for (k = nn - nempty ; k < nn ; k++) + { + oldcol = Cperm1 [k] ; + i = k ; + oldrow = Rperm1 [k] ; + W [oldcol] = oldrow ; + } + for (k = 0 ; k < nn ; k++) + { + Rperm_2by2 [k] = W [k] ; + } + + /* Now, the "diagonal" entry in oldcol (where oldcol is the user's + * name for a column, is the entry in row oldrow (where oldrow is + * the user's name for a row, and oldrow = Rperm_2by2 [oldcol] */ + } + + /* Fr_* no longer needed for Rp, Blen, W ] */ + } + + /* ---------------------------------------------------------------------- */ + /* finalize the strategy, including fixQ and prefer_diagonal */ + /* ---------------------------------------------------------------------- */ + + if (strategy == UMFPACK_STRATEGY_SYMMETRIC) + { + /* use given Quser or AMD (A+A'), fix Q during factorization, + * prefer diagonal */ + DEBUG0 (("\nStrategy: symmetric\n")) ; + ASSERT (n_row == n_col) ; + Symbolic->ordering = UMFPACK_ORDERING_AMD ; + fixQ = TRUE ; + prefer_diagonal = TRUE ; + } + else if (strategy == UMFPACK_STRATEGY_2BY2) + { + /* use Q = given Quser or Q = AMD (PA+PA'), fix Q during factorization, + * prefer diagonal, and factorize PAQ, where P is found by UMF_2by2. */ + DEBUG0 (("\nStrategy: symmetric 2-by-2\n")) ; + ASSERT (n_row == n_col) ; + Symbolic->ordering = UMFPACK_ORDERING_AMD ; + fixQ = TRUE ; + prefer_diagonal = TRUE ; + } + else + { + /* use given Quser or COLAMD (A), refine Q during factorization, + * no diagonal preference */ + ASSERT (strategy == UMFPACK_STRATEGY_UNSYMMETRIC) ; + DEBUG0 (("\nStrategy: unsymmetric\n")) ; + Symbolic->ordering = UMFPACK_ORDERING_COLAMD ; + fixQ = FALSE ; + prefer_diagonal = FALSE ; + } + + if (Quser != (Int *) NULL) + { + Symbolic->ordering = UMFPACK_ORDERING_GIVEN ; + } + + if (force_fixQ > 0) + { + fixQ = TRUE ; + DEBUG0 (("Force fixQ true\n")) ; + } + else if (force_fixQ < 0) + { + fixQ = FALSE ; + DEBUG0 (("Force fixQ false\n")) ; + } + + DEBUG0 (("Strategy: ordering: "ID"\n", Symbolic->ordering)) ; + DEBUG0 (("Strategy: fixQ: "ID"\n", fixQ)) ; + DEBUG0 (("Strategy: prefer diag "ID"\n", prefer_diagonal)) ; + + /* get statistics from amd_aat, if computed */ + Symbolic->strategy = strategy ; + Symbolic->fixQ = fixQ ; + Symbolic->prefer_diagonal = prefer_diagonal ; + + Info [UMFPACK_STRATEGY_USED] = strategy ; + Info [UMFPACK_ORDERING_USED] = Symbolic->ordering ; + Info [UMFPACK_QFIXED] = fixQ ; + Info [UMFPACK_DIAG_PREFERRED] = prefer_diagonal ; + + /* ---------------------------------------------------------------------- */ + /* get the AMD ordering for the symmetric strategy */ + /* ---------------------------------------------------------------------- */ + + if (strategy == UMFPACK_STRATEGY_SYMMETRIC && Quser == (Int *) NULL) + { + /* symmetric strategy for a matrix with mostly symmetric pattern */ + Int *Qinv = Fr_npivcol ; + ASSERT (n_row == n_col && nn == n_row) ; + ASSERT (Clen >= (nzaat + nzaat/5 + nn) + 7*nn) ; + do_amd (n2, Sp, Si, Wq, Qinv, Sdeg, Clen, Ci, + amd_Control, amd_Info, Symbolic, Info) ; + /* combine the singleton ordering and the AMD ordering */ + combine_ordering (n1, nempty, nn, Cperm_init, Cperm1, Qinv) ; + } + /* Sdeg no longer needed ] */ + /* done using Rperm_init as workspace for Wq ] */ + + /* Contents of Si and Sp no longer needed, but the space is still needed */ + + /* ---------------------------------------------------------------------- */ + /* use the user's input column ordering (already in Cperm1) */ + /* ---------------------------------------------------------------------- */ + + if (Quser != (Int *) NULL) + { + for (k = 0 ; k < n_col ; k++) + { + Cperm_init [k] = Cperm1 [k] ; + } + } + + /* ---------------------------------------------------------------------- */ + /* use COLAMD to order the matrix */ + /* ---------------------------------------------------------------------- */ + + if (strategy == UMFPACK_STRATEGY_UNSYMMETRIC && Quser == (Int *) NULL) + { + + /* ------------------------------------------------------------------ */ + /* copy the matrix into colamd workspace (colamd destroys its input) */ + /* ------------------------------------------------------------------ */ + + /* C = A (Cperm1 (n1+1:end), Rperm1 (n1+1:end)), where Ci is used as + * the row indices and Cperm_init (on input) is used as the column + * pointers. */ + + (void) prune_singletons (n1, n_col, Ap, Ai, + (double *) NULL, +#ifdef COMPLEX + (double *) NULL, +#endif + Cperm1, InvRperm1, Ci, Cperm_init +#ifndef NDEBUG + , Rperm1, n_row +#endif + ) ; + + /* ------------------------------------------------------------------ */ + /* set UMF_colamd defaults */ + /* ------------------------------------------------------------------ */ + + UMF_colamd_set_defaults (knobs) ; + knobs [COLAMD_DENSE_ROW] = drow ; + knobs [COLAMD_DENSE_COL] = dcol ; + knobs [COLAMD_AGGRESSIVE] = aggressive ; + + /* ------------------------------------------------------------------ */ + /* check input matrix and find the initial column pre-ordering */ + /* ------------------------------------------------------------------ */ + + /* NOTE: umf_colamd is not given any original empty rows or columns. + * Those have already been removed via prune_singletons, above. The + * umf_colamd routine has been modified to assume that all rows and + * columns have at least one entry in them. It will break if it is + * given empty rows or columns (an assertion is triggered when running + * in debug mode. */ + + (void) UMF_colamd ( + n_row - n1 - nempty_row, + n_col - n1 - nempty_col, + Clen, Ci, Cperm_init, knobs, colamd_stats, + Fr_npivcol, Fr_nrows, Fr_ncols, Fr_parent, Fr_cols, &nfr, + InFront) ; + ASSERT (colamd_stats [COLAMD_EMPTY_ROW] == 0) ; + ASSERT (colamd_stats [COLAMD_EMPTY_COL] == 0) ; + + /* # of dense rows will be recomputed below */ + Info [UMFPACK_NDENSE_ROW] = colamd_stats [COLAMD_DENSE_ROW] ; + Info [UMFPACK_NDENSE_COL] = colamd_stats [COLAMD_DENSE_COL] ; + Info [UMFPACK_SYMBOLIC_DEFRAG] = colamd_stats [COLAMD_DEFRAG_COUNT] ; + + /* re-analyze if any "dense" rows or cols ignored by UMF_colamd */ + do_UMF_analyze = + colamd_stats [COLAMD_DENSE_ROW] > 0 || + colamd_stats [COLAMD_DENSE_COL] > 0 ; + + /* Combine the singleton and colamd ordering into Cperm_init */ + /* Note that colamd returns its inverse permutation in Ci */ + combine_ordering (n1, nempty_col, n_col, Cperm_init, Cperm1, Ci) ; + + /* contents of Ci no longer needed */ + +#ifndef NDEBUG + for (col = 0 ; col < n_col ; col++) + { + DEBUG1 (("Cperm_init ["ID"] = "ID"\n", col, Cperm_init[col])); + } + /* make sure colamd returned a valid permutation */ + ASSERT (Cperm_init != (Int *) NULL) ; + ASSERT (UMF_is_permutation (Cperm_init, Ci, n_col, n_col)) ; +#endif + + } + else + { + + /* ------------------------------------------------------------------ */ + /* do not call colamd - use input Quser or AMD instead */ + /* ------------------------------------------------------------------ */ + + /* The ordering (Quser or Qamd) is already in Cperm_init */ + do_UMF_analyze = TRUE ; + + } + + Cperm_init [n_col] = EMPTY ; /* unused in Cperm_init */ + + /* ---------------------------------------------------------------------- */ + /* AMD ordering, if it exists, has been copied into Cperm_init */ + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + DEBUG3 (("Cperm_init column permutation:\n")) ; + ASSERT (UMF_is_permutation (Cperm_init, Ci, n_col, n_col)) ; + for (k = 0 ; k < n_col ; k++) + { + DEBUG3 ((ID"\n", Cperm_init [k])) ; + } + /* ensure that empty columns have been placed last in A (:,Cperm_init) */ + for (newj = 0 ; newj < n_col ; newj++) + { + /* empty columns will be last in A (:, Cperm_init (1:n_col)) */ + j = Cperm_init [newj] ; + ASSERT (IMPLIES (newj >= n_col-nempty_col, Cdeg [j] == 0)) ; + ASSERT (IMPLIES (newj < n_col-nempty_col, Cdeg [j] > 0)) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization (unless colamd has already done it) */ + /* ---------------------------------------------------------------------- */ + + if (do_UMF_analyze) + { + + Int *W, *Bp, *Bi, *Cperm2, ok, *P, Clen2, bsize, Clen0 ; + + /* ------------------------------------------------------------------ */ + /* construct column pre-ordered, pruned submatrix */ + /* ------------------------------------------------------------------ */ + + /* S = column form submatrix after removing singletons and applying + * initial column ordering (includes singleton ordering) */ + (void) prune_singletons (n1, n_col, Ap, Ai, + (double *) NULL, +#ifdef COMPLEX + (double *) NULL, +#endif + Cperm_init, InvRperm1, Si, Sp +#ifndef NDEBUG + , Rperm1, n_row +#endif + ) ; + + /* ------------------------------------------------------------------ */ + /* Ci [0 .. Clen-1] holds the following work arrays: + + first Clen0 entries empty space, where Clen0 = + Clen - (nn+1 + 2*nn + n_col) + and Clen0 >= nz + n_col + next nn+1 entries Bp [0..nn] + next nn entries Link [0..nn-1] + next nn entries W [0..nn-1] + last n_col entries Cperm2 [0..n_col-1] + + We have Clen >= n_col + MAX (nz,n_col) + 3*nn+1 + n_col, + So Clen0 >= 2*n_col as required for AMD_postorder + and Clen0 >= n_col + nz as required + */ + + Clen0 = Clen - (nn+1 + 2*nn + n_col) ; + Bp = Ci + Clen0 ; + Link = Bp + (nn+1) ; + W = Link + nn ; + Cperm2 = W + nn ; + ASSERT (Cperm2 + n_col == Ci + Clen) ; + ASSERT (Clen0 >= nz + n_col) ; + ASSERT (Clen0 >= 2*n_col) ; + + /* ------------------------------------------------------------------ */ + /* P = order that rows will be used in UMF_analyze */ + /* ------------------------------------------------------------------ */ + + /* use W to mark rows, and use Link for row permutation P [ [ */ + for (row = 0 ; row < n_row - n1 ; row++) + { + W [row] = FALSE ; + } + P = Link ; + + k = 0 ; + + for (col = 0 ; col < n_col - n1 ; col++) + { + /* empty columns are last in S */ + for (p = Sp [col] ; p < Sp [col+1] ; p++) + { + row = Si [p] ; + if (!W [row]) + { + /* this row has just been seen for the first time */ + W [row] = TRUE ; + P [k++] = row ; + } + } + } + + /* If the matrix has truly empty rows, then P will not be */ + /* complete, and visa versa. The matrix is structurally singular. */ + nempty_row = n_row - n1 - k ; + if (k < n_row - n1) + { + /* complete P by putting empty rows last in their natural order, */ + /* rather than declaring an error (the matrix is singular) */ + for (row = 0 ; row < n_row - n1 ; row++) + { + if (!W [row]) + { + /* W [row] = TRUE ; (not required) */ + P [k++] = row ; + } + } + } + + /* contents of W no longer needed ] */ + +#ifndef NDEBUG + DEBUG3 (("Induced row permutation:\n")) ; + ASSERT (k == n_row - n1) ; + ASSERT (UMF_is_permutation (P, W, n_row - n1, n_row - n1)) ; + for (k = 0 ; k < n_row - n1 ; k++) + { + DEBUG3 ((ID"\n", P [k])) ; + } +#endif + + /* ------------------------------------------------------------------ */ + /* B = row-form of the pattern of S (excluding empty columns) */ + /* ------------------------------------------------------------------ */ + + /* Ci [0 .. Clen-1] holds the following work arrays: + + first Clen2 entries empty space, must be at least >= n_col + next max (nz,1) Bi [0..max (nz,1)-1] + next nn+1 entries Bp [0..nn] + next nn entries Link [0..nn-1] + next nn entries W [0..nn-1] + last n_col entries Cperm2 [0..n_col-1] + + This memory usage is accounted for by the UMF_ANALYZE_CLEN + macro. + */ + + Clen2 = Clen0 ; + snz = Sp [n_col - n1] ; + bsize = MAX (snz, 1) ; + Clen2 -= bsize ; + Bi = Ci + Clen2 ; + ASSERT (Clen2 >= n_col) ; + + (void) UMF_transpose (n_row - n1, n_col - n1 - nempty_col, + Sp, Si, (double *) NULL, + P, (Int *) NULL, 0, Bp, Bi, (double *) NULL, W, FALSE +#ifdef COMPLEX + , (double *) NULL, (double *) NULL, FALSE +#endif + ) ; + + /* contents of Si and Sp no longer needed */ + + /* contents of P (same as Link) and W not needed */ + /* still need Link and W as work arrays, though ] */ + + ASSERT (Bp [0] == 0) ; + ASSERT (Bp [n_row - n1] == snz) ; + + /* increment Bp to point into Ci, not Bi */ + for (i = 0 ; i <= n_row - n1 ; i++) + { + Bp [i] += Clen2 ; + } + ASSERT (Bp [0] == Clen0 - bsize) ; + ASSERT (Bp [n_row - n1] <= Clen0) ; + + /* Ci [0 .. Clen-1] holds the following work arrays: + + first Clen0 entries Ci [0 .. Clen0-1], where the col indices + of B are at the tail end of this part, + and Bp [0] = Clen2 >= n_col. Note + that Clen0 = Clen2 + max (snz,1). + next nn+1 entries Bp [0..nn] + next nn entries Link [0..nn-1] + next nn entries W [0..nn-1] + last n_col entries Cperm2 [0..n_col-1] + */ + + /* ------------------------------------------------------------------ */ + /* analyze */ + /* ------------------------------------------------------------------ */ + + /* only analyze the non-empty, non-singleton part of the matrix */ + ok = UMF_analyze ( + n_row - n1 - nempty_row, + n_col - n1 - nempty_col, + Ci, Bp, Cperm2, fixQ, W, Link, + Fr_ncols, Fr_nrows, Fr_npivcol, + Fr_parent, &nfr, &analyze_compactions) ; + if (!ok) + { + /* :: internal error in umf_analyze :: */ + Info [UMFPACK_STATUS] = UMFPACK_ERROR_internal_error ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_internal_error) ; + } + Info [UMFPACK_SYMBOLIC_DEFRAG] += analyze_compactions ; + + /* ------------------------------------------------------------------ */ + /* combine the input permutation and UMF_analyze's permutation */ + /* ------------------------------------------------------------------ */ + + if (!fixQ) + { + /* Cperm2 is the column etree post-ordering */ + ASSERT (UMF_is_permutation (Cperm2, W, + n_col-n1-nempty_col, n_col-n1-nempty_col)) ; + + /* Note that the empty columns remain at the end of Cperm_init */ + for (k = 0 ; k < n_col - n1 - nempty_col ; k++) + { + W [k] = Cperm_init [n1 + Cperm2 [k]] ; + } + + for (k = 0 ; k < n_col - n1 - nempty_col ; k++) + { + Cperm_init [n1 + k] = W [k] ; + } + } + + ASSERT (UMF_is_permutation (Cperm_init, W, n_col, n_col)) ; + + } + + /* ---------------------------------------------------------------------- */ + /* free some of the workspace */ + /* ---------------------------------------------------------------------- */ + + /* (4) The real workspace, Rs, of size n_row doubles has already been + * free'd. An additional workspace of size nz + n_col+1 + n_col integers + * is now free'd as well. */ + + SW->Si = (Int *) UMF_free ((void *) SW->Si) ; + SW->Sp = (Int *) UMF_free ((void *) SW->Sp) ; + SW->Cperm1 = (Int *) UMF_free ((void *) SW->Cperm1) ; + ASSERT (SW->Rs == (double *) NULL) ; + + /* ---------------------------------------------------------------------- */ + /* determine the size of the Symbolic object */ + /* ---------------------------------------------------------------------- */ + + /* ---------------------------------------------------------------------- */ + /* determine the size of the Symbolic object */ + /* ---------------------------------------------------------------------- */ + + nchains = 0 ; + for (i = 0 ; i < nfr ; i++) + { + if (Fr_parent [i] != i+1) + { + nchains++ ; + } + } + + Symbolic->nchains = nchains ; + Symbolic->nfr = nfr ; + Symbolic->esize + = (max_rdeg > dense_row_threshold) ? (n_col - n1 - nempty_col) : 0 ; + + /* true size of Symbolic object */ + Info [UMFPACK_SYMBOLIC_SIZE] = UMF_symbolic_usage (n_row, n_col, nchains, + nfr, Symbolic->esize, prefer_diagonal) ; + + /* actual peak memory usage for UMFPACK_symbolic (actual nfr, nchains) */ + Info [UMFPACK_SYMBOLIC_PEAK_MEMORY] = + SYM_WORK_USAGE (n_col, n_row, Clen) + Info [UMFPACK_SYMBOLIC_SIZE] ; + Symbolic->peak_sym_usage = Info [UMFPACK_SYMBOLIC_PEAK_MEMORY] ; + + DEBUG0 (("Number of fronts: "ID"\n", nfr)) ; + + /* ---------------------------------------------------------------------- */ + /* allocate the second part of the Symbolic object (Front_*, Chain_*) */ + /* ---------------------------------------------------------------------- */ + + /* (5) UMF_malloc is called 7 or 8 times, for a total space of + * (4*(nfr+1) + 3*(nchains+1) + esize) integers, where nfr is the total + * number of frontal matrices and nchains is the total number of frontal + * matrix chains, and where nchains <= nfr <= n_col. esize is zero if there + * are no dense rows, or n_col-n1-nempty_col otherwise (n1 is the number of + * singletons and nempty_col is the number of empty columns). This space is + * part of the Symbolic object and is not free'd unless an error occurs. + * This is between 7 and about 8n integers when A is square. + */ + + /* Note that Symbolic->Front_* does include the dummy placeholder front */ + Symbolic->Front_npivcol = (Int *) UMF_malloc (nfr+1, sizeof (Int)) ; + Symbolic->Front_parent = (Int *) UMF_malloc (nfr+1, sizeof (Int)) ; + Symbolic->Front_1strow = (Int *) UMF_malloc (nfr+1, sizeof (Int)) ; + Symbolic->Front_leftmostdesc = (Int *) UMF_malloc (nfr+1, sizeof (Int)) ; + Symbolic->Chain_start = (Int *) UMF_malloc (nchains+1, sizeof (Int)) ; + Symbolic->Chain_maxrows = (Int *) UMF_malloc (nchains+1, sizeof (Int)) ; + Symbolic->Chain_maxcols = (Int *) UMF_malloc (nchains+1, sizeof (Int)) ; + + fail = (!Symbolic->Front_npivcol || !Symbolic->Front_parent || + !Symbolic->Front_1strow || !Symbolic->Front_leftmostdesc || + !Symbolic->Chain_start || !Symbolic->Chain_maxrows || + !Symbolic->Chain_maxcols) ; + + if (Symbolic->esize > 0) + { + Symbolic->Esize = (Int *) UMF_malloc (Symbolic->esize, sizeof (Int)) ; + fail = fail || !Symbolic->Esize ; + } + + if (fail) + { + DEBUGm4 (("out of memory: rest of symbolic object\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + DEBUG0 (("Symbolic UMF_malloc_count - init_count = "ID"\n", + UMF_malloc_count - init_count)) ; + ASSERT (UMF_malloc_count == init_count + 21 + + (SW->Rperm_2by2 != (Int *) NULL) + + (Symbolic->Esize != (Int *) NULL)) ; + + Front_npivcol = Symbolic->Front_npivcol ; + Front_parent = Symbolic->Front_parent ; + Front_1strow = Symbolic->Front_1strow ; + Front_leftmostdesc = Symbolic->Front_leftmostdesc ; + + Chain_start = Symbolic->Chain_start ; + Chain_maxrows = Symbolic->Chain_maxrows ; + Chain_maxcols = Symbolic->Chain_maxcols ; + + Esize = Symbolic->Esize ; + + /* ---------------------------------------------------------------------- */ + /* assign rows to fronts */ + /* ---------------------------------------------------------------------- */ + + /* find InFront, unless colamd has already computed it */ + if (do_UMF_analyze) + { + + DEBUGm4 ((">>>>>>>>>Computing Front_1strow from scratch\n")) ; + /* empty rows go to dummy front nfr */ + for (row = 0 ; row < n_row ; row++) + { + InFront [row] = nfr ; + } + /* assign the singleton pivot rows to the "empty" front */ + for (k = 0 ; k < n1 ; k++) + { + row = Rperm1 [k] ; + InFront [row] = EMPTY ; + } + DEBUG1 (("Front (EMPTY), singleton nrows "ID" ncols "ID"\n", k, k)) ; + newj = n1 ; + for (i = 0 ; i < nfr ; i++) + { + fpivcol = Fr_npivcol [i] ; + f1rows = 0 ; + /* for all pivot columns in front i */ + for (kk = 0 ; kk < fpivcol ; kk++, newj++) + { + j = Cperm_init [newj] ; + ASSERT (IMPLIES (newj >= n_col-nempty_col, + Ap [j+1] - Ap [j] == 0)); + for (p = Ap [j] ; p < Ap [j+1] ; p++) + { + row = Ai [p] ; + if (InFront [row] == nfr) + { + /* this row belongs to front i */ + DEBUG1 ((" Row "ID" in Front "ID"\n", row, i)) ; + InFront [row] = i ; + f1rows++ ; + } + } + } + Front_1strow [i] = f1rows ; + DEBUG1 ((" Front "ID" has 1strows: "ID" pivcols "ID"\n", + i, f1rows, fpivcol)) ; + } + + } + else + { + + /* COLAMD has already computed InFront, but it is not yet + * InFront [row] = front i, where row is an original row. It is + * InFront [k-n1] = i for k in the range n1 to n_row-nempty_row, + * and where row = Rperm1 [k]. Need to permute InFront. Also compute + * # of original rows assembled into each front. + * [ use Ci as workspace */ + DEBUGm4 ((">>>>>>>>>Computing Front_1strow from colamd's InFront\n")) ; + for (i = 0 ; i <= nfr ; i++) + { + Front_1strow [i] = 0 ; + } + /* assign the singleton pivot rows to "empty" front */ + for (k = 0 ; k < n1 ; k++) + { + row = Rperm1 [k] ; + Ci [row] = EMPTY ; + } + /* assign the non-empty rows to the front that assembled them */ + for ( ; k < n_row - nempty_row ; k++) + { + row = Rperm1 [k] ; + i = InFront [k - n1] ; + ASSERT (i >= EMPTY && i < nfr) ; + if (i != EMPTY) + { + Front_1strow [i]++ ; + } + /* use Ci as permuted version of InFront */ + Ci [row] = i ; + } + /* empty rows go to the "dummy" front */ + for ( ; k < n_row ; k++) + { + row = Rperm1 [k] ; + Ci [row] = nfr ; + } + /* permute InFront so that InFront [row] = i if the original row is + * in front i */ + for (row = 0 ; row < n_row ; row++) + { + InFront [row] = Ci [row] ; + } + /* ] no longer need Ci as workspace */ + } + +#ifndef NDEBUG + for (row = 0 ; row < n_row ; row++) + { + if (InFront [row] == nfr) + { + DEBUG1 ((" Row "ID" in Dummy Front "ID"\n", row, nfr)) ; + } + else if (InFront [row] == EMPTY) + { + DEBUG1 ((" singleton Row "ID"\n", row)) ; + } + else + { + DEBUG1 ((" Row "ID" in Front "ID"\n", row, nfr)) ; + } + } + for (i = 0 ; i <= nfr ; i++) + { + DEBUG1 (("Front "ID" has 1strows: "ID" pivcols "ID"\n", + i, f1rows, fpivcol)) ; + } +#endif + + /* ---------------------------------------------------------------------- */ + /* copy front information into Symbolic object */ + /* ---------------------------------------------------------------------- */ + + k = n1 ; + for (i = 0 ; i < nfr ; i++) + { + fpivcol = Fr_npivcol [i] ; + DEBUG1 (("Front "ID" k "ID" npivcol "ID" nrows "ID" ncols "ID"\n", + i, k, fpivcol, Fr_nrows [i], Fr_ncols [i])) ; + k += fpivcol ; + /* copy Front info into Symbolic object from SW */ + Front_npivcol [i] = fpivcol ; + Front_parent [i] = Fr_parent [i] ; + } + + /* assign empty columns to dummy placehold front nfr */ + DEBUG1 (("Dummy Cols in Front "ID" : "ID"\n", nfr, n_col-k)) ; + Front_npivcol [nfr] = n_col - k ; + Front_parent [nfr] = EMPTY ; + + /* ---------------------------------------------------------------------- */ + /* find initial row permutation */ + /* ---------------------------------------------------------------------- */ + + /* order the singleton pivot rows */ + for (k = 0 ; k < n1 ; k++) + { + Rperm_init [k] = Rperm1 [k] ; + } + + /* determine the first row in each front (in the new row ordering) */ + for (i = 0 ; i < nfr ; i++) + { + f1rows = Front_1strow [i] ; + DEBUG1 (("Front "ID" : npivcol "ID" parent "ID, + i, Front_npivcol [i], Front_parent [i])) ; + DEBUG1 ((" 1st rows in Front "ID" : "ID"\n", i, f1rows)) ; + Front_1strow [i] = k ; + k += f1rows ; + } + + /* assign empty rows to dummy placehold front nfr */ + DEBUG1 (("Rows in Front "ID" (dummy): "ID"\n", nfr, n_row-k)) ; + Front_1strow [nfr] = k ; + DEBUG1 (("nfr "ID" 1strow[nfr] "ID" nrow "ID"\n", nfr, k, n_row)) ; + + /* Use Ci as temporary workspace for F1 */ + F1 = Ci ; /* [ of size nfr+1 */ + ASSERT (Clen >= 2*n_row + nfr+1) ; + + for (i = 0 ; i <= nfr ; i++) + { + F1 [i] = Front_1strow [i] ; + } + + for (row = 0 ; row < n_row ; row++) + { + i = InFront [row] ; + if (i != EMPTY) + { + newrow = F1 [i]++ ; + ASSERT (newrow >= n1) ; + Rperm_init [newrow] = row ; + } + } + Rperm_init [n_row] = EMPTY ; /* unused */ + +#ifndef NDEBUG + for (k = 0 ; k < n_row ; k++) + { + DEBUG2 (("Rperm_init ["ID"] = "ID"\n", k, Rperm_init [k])) ; + } +#endif + + /* ] done using F1 */ + + /* ---------------------------------------------------------------------- */ + /* find the diagonal map */ + /* ---------------------------------------------------------------------- */ + + /* Rperm_init [newrow] = row gives the row permutation that is implied + * by the column permutation, where "row" is a row index of the original + * matrix A. It is not dependent on the Rperm_2by2 permutation, which + * only redefines the "diagonal". Both are used to construct the + * Diagonal_map. Diagonal_map only needs to be defined for + * k = n1 to nn - nempty, but go ahead and define it for all of + * k = 0 to nn */ + + if (prefer_diagonal) + { + Int *Diagonal_map ; + ASSERT (n_row == n_col && nn == n_row) ; + ASSERT (nempty_row == nempty_col && nempty == nempty_row) ; + + /* allocate the Diagonal_map */ + Symbolic->Diagonal_map = (Int *) UMF_malloc (n_col+1, sizeof (Int)) ; + Diagonal_map = Symbolic->Diagonal_map ; + if (Diagonal_map == (Int *) NULL) + { + /* :: out of memory (diagonal map) :: */ + DEBUGm4 (("out of memory: Diagonal map\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + error (&Symbolic, SW) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + /* use Ci as workspace to compute the inverse of Rperm_init [ */ + for (newrow = 0 ; newrow < nn ; newrow++) + { + oldrow = Rperm_init [newrow] ; + ASSERT (oldrow >= 0 && oldrow < nn) ; + Ci [oldrow] = newrow ; + } + if (strategy == UMFPACK_STRATEGY_2BY2) + { + ASSERT (Rperm_2by2 != (Int *) NULL) ; + for (newcol = 0 ; newcol < nn ; newcol++) + { + oldcol = Cperm_init [newcol] ; + /* 2-by-2 pivoting done in S */ + oldrow = Rperm_2by2 [oldcol] ; + newrow = Ci [oldrow] ; + Diagonal_map [newcol] = newrow ; + } + } + else + { + for (newcol = 0 ; newcol < nn ; newcol++) + { + oldcol = Cperm_init [newcol] ; + /* no 2-by-2 pivoting in S */ + oldrow = oldcol ; + newrow = Ci [oldrow] ; + Diagonal_map [newcol] = newrow ; + } + } + +#ifndef NDEBUG + DEBUG1 (("\nDiagonal map:\n")) ; + for (newcol = 0 ; newcol < nn ; newcol++) + { + oldcol = Cperm_init [newcol] ; + DEBUG3 (("oldcol "ID" newcol "ID":\n", oldcol, newcol)) ; + for (p = Ap [oldcol] ; p < Ap [oldcol+1] ; p++) + { + Entry aij ; + oldrow = Ai [p] ; + newrow = Ci [oldrow] ; + if (Ax != (double *) NULL) + { + ASSIGN (aij, Ax, Az, p, SPLIT (Az)) ; + } + if (oldrow == oldcol) + { + DEBUG2 ((" old diagonal : oldcol "ID" oldrow "ID" ", + oldcol, oldrow)) ; + EDEBUG2 (aij) ; + DEBUG2 (("\n")) ; + } + if (newrow == Diagonal_map [newcol]) + { + DEBUG2 ((" MAP diagonal : newcol "ID" MAProw "ID" ", + newcol, Diagonal_map [newrow])) ; + EDEBUG2 (aij) ; + DEBUG2 (("\n")) ; + } + } + } +#endif + /* done using Ci as workspace ] */ + + } + + /* ---------------------------------------------------------------------- */ + /* find the leftmost descendant of each front */ + /* ---------------------------------------------------------------------- */ + + for (i = 0 ; i <= nfr ; i++) + { + Front_leftmostdesc [i] = EMPTY ; + } + + for (i = 0 ; i < nfr ; i++) + { + /* start at i and walk up the tree */ + DEBUG2 (("Walk up front tree from "ID"\n", i)) ; + j = i ; + while (j != EMPTY && Front_leftmostdesc [j] == EMPTY) + { + DEBUG3 ((" Leftmost desc of "ID" is "ID"\n", j, i)) ; + Front_leftmostdesc [j] = i ; + j = Front_parent [j] ; + DEBUG3 ((" go to j = "ID"\n", j)) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* find the frontal matrix chains and max frontal matrix sizes */ + /* ---------------------------------------------------------------------- */ + + maxnrows = 1 ; /* max # rows in any front */ + maxncols = 1 ; /* max # cols in any front */ + dmaxfrsize = 1 ; /* max frontal matrix size */ + + /* start the first chain */ + nchains = 0 ; /* number of chains */ + Chain_start [0] = 0 ; /* front 0 starts a new chain */ + maxrows = 1 ; /* max # rows for any front in current chain */ + maxcols = 1 ; /* max # cols for any front in current chain */ + DEBUG1 (("Constructing chains:\n")) ; + + for (i = 0 ; i < nfr ; i++) + { + /* get frontal matrix info */ + fpivcol = Front_npivcol [i] ; /* # candidate pivot columns */ + fallrows = Fr_nrows [i] ; /* all rows (not just Schur comp) */ + fallcols = Fr_ncols [i] ; /* all cols (not just Schur comp) */ + parent = Front_parent [i] ; /* parent in column etree */ + fpiv = MIN (fpivcol, fallrows) ; /* # pivot rows and cols */ + maxrows = MAX (maxrows, fallrows) ; + maxcols = MAX (maxcols, fallcols) ; + + DEBUG1 (("Front: "ID", pivcol "ID", "ID"-by-"ID" parent "ID + ", npiv "ID" Chain: maxrows "ID" maxcols "ID"\n", i, fpivcol, + fallrows, fallcols, parent, fpiv, maxrows, maxcols)) ; + + if (parent != i+1) + { + /* this is the end of a chain */ + double s ; + DEBUG1 (("\nEnd of chain "ID"\n", nchains)) ; + + /* make sure maxrows is an odd number */ + ASSERT (maxrows >= 0) ; + if (maxrows % 2 == 0) maxrows++ ; + + DEBUG1 (("Chain maxrows "ID" maxcols "ID"\n", maxrows, maxcols)) ; + + Chain_maxrows [nchains] = maxrows ; + Chain_maxcols [nchains] = maxcols ; + + /* keep track of the maximum front size for all chains */ + + /* for Info only: */ + s = (double) maxrows * (double) maxcols ; + dmaxfrsize = MAX (dmaxfrsize, s) ; + + /* for the subsequent numerical factorization */ + maxnrows = MAX (maxnrows, maxrows) ; + maxncols = MAX (maxncols, maxcols) ; + + DEBUG1 (("Chain dmaxfrsize %g\n\n", dmaxfrsize)) ; + + /* start the next chain */ + nchains++ ; + Chain_start [nchains] = i+1 ; + maxrows = 1 ; + maxcols = 1 ; + } + } + + /* for Info only: */ + dmaxfrsize = ceil (dmaxfrsize) ; + DEBUGm1 (("dmaxfrsize %30.20g Int_MAX "ID"\n", dmaxfrsize, Int_MAX)) ; + ASSERT (Symbolic->nchains == nchains) ; + + /* For allocating objects in umfpack_numeric (does not include all possible + * pivots, particularly pivots from prior fronts in the chain. Need to add + * nb to these to get the # of columns in the L block, for example. This + * is the largest row dimension and largest column dimension of any frontal + * matrix. maxnrows is always odd. */ + Symbolic->maxnrows = maxnrows ; + Symbolic->maxncols = maxncols ; + DEBUGm3 (("maxnrows "ID" maxncols "ID"\n", maxnrows, maxncols)) ; + + /* ---------------------------------------------------------------------- */ + /* find the initial element sizes */ + /* ---------------------------------------------------------------------- */ + + if (max_rdeg > dense_row_threshold) + { + /* there are one or more dense rows in the input matrix */ + /* count the number of dense rows in each column */ + /* use Ci as workspace for inverse of Rperm_init [ */ + ASSERT (Esize != (Int *) NULL) ; + for (newrow = 0 ; newrow < n_row ; newrow++) + { + oldrow = Rperm_init [newrow] ; + ASSERT (oldrow >= 0 && oldrow < nn) ; + Ci [oldrow] = newrow ; + } + for (col = n1 ; col < n_col - nempty_col ; col++) + { + oldcol = Cperm_init [col] ; + esize = Cdeg [oldcol] ; + ASSERT (esize > 0) ; + for (p = Ap [oldcol] ; p < Ap [oldcol+1] ; p++) + { + oldrow = Ai [p] ; + newrow = Ci [oldrow] ; + if (newrow >= n1 && Rdeg [oldrow] > dense_row_threshold) + { + esize-- ; + } + } + ASSERT (esize >= 0) ; + Esize [col - n1] = esize ; + } + /* done using Ci as workspace ] */ + } + + /* If there are no dense rows, then Esize [col-n1] is identical to + * Cdeg [col], once Cdeg is permuted below */ + + /* ---------------------------------------------------------------------- */ + /* permute Cdeg and Rdeg according to initial column and row permutation */ + /* ---------------------------------------------------------------------- */ + + /* use Ci as workspace [ */ + for (k = 0 ; k < n_col ; k++) + { + Ci [k] = Cdeg [Cperm_init [k]] ; + } + for (k = 0 ; k < n_col ; k++) + { + Cdeg [k] = Ci [k] ; + } + for (k = 0 ; k < n_row ; k++) + { + Ci [k] = Rdeg [Rperm_init [k]] ; + } + for (k = 0 ; k < n_row ; k++) + { + Rdeg [k] = Ci [k] ; + } + /* done using Ci as workspace ] */ + + /* ---------------------------------------------------------------------- */ + /* simulate UMF_kernel_init */ + /* ---------------------------------------------------------------------- */ + + /* count elements and tuples at tail, LU factors of singletons, and + * head and tail markers */ + + dlnz = n_inner ; /* upper limit of nz in L (incl diag) */ + dunz = dlnz ; /* upper limit of nz in U (incl diag) */ + + /* head marker */ + head_usage = 1 ; + dhead_usage = 1 ; + + /* tail markers: */ + tail_usage = 2 ; + dtail_usage = 2 ; + + /* allocate the Rpi and Rpx workspace for UMF_kernel_init (incl. headers) */ + tail_usage += UNITS (Int *, n_row+1) + UNITS (Entry *, n_row+1) + 2 ; + dtail_usage += DUNITS (Int *, n_row+1) + DUNITS (Entry *, n_row+1) + 2 ; + DEBUG1 (("Symbolic usage after Rpi/Rpx allocation: head "ID" tail "ID"\n", + head_usage, tail_usage)) ; + + /* LU factors for singletons, at the head of memory */ + for (k = 0 ; k < n1 ; k++) + { + lnz = Cdeg [k] - 1 ; + unz = Rdeg [k] - 1 ; + dlnz += lnz ; + dunz += unz ; + DEBUG1 (("singleton k "ID" pivrow "ID" pivcol "ID" lnz "ID" unz "ID"\n", + k, Rperm_init [k], Cperm_init [k], lnz, unz)) ; + head_usage += UNITS (Int, lnz) + UNITS (Entry, lnz) + + UNITS (Int, unz) + UNITS (Entry, unz) ; + dhead_usage += DUNITS (Int, lnz) + DUNITS (Entry, lnz) + + DUNITS (Int, unz) + DUNITS (Entry, unz) ; + } + DEBUG1 (("Symbolic init head usage: "ID" for LU singletons\n",head_usage)) ; + + /* column elements: */ + for (k = n1 ; k < n_col - nempty_col; k++) + { + esize = Esize ? Esize [k-n1] : Cdeg [k] ; + DEBUG2 ((" esize: "ID"\n", esize)) ; + ASSERT (esize >= 0) ; + if (esize > 0) + { + tail_usage += GET_ELEMENT_SIZE (esize, 1) + 1 ; + dtail_usage += DGET_ELEMENT_SIZE (esize, 1) + 1 ; + } + } + + /* dense row elements */ + if (Esize) + { + Int nrow_elements = 0 ; + for (k = n1 ; k < n_row - nempty_row ; k++) + { + rdeg = Rdeg [k] ; + if (rdeg > dense_row_threshold) + { + tail_usage += GET_ELEMENT_SIZE (1, rdeg) + 1 ; + dtail_usage += GET_ELEMENT_SIZE (1, rdeg) + 1 ; + nrow_elements++ ; + } + } + Info [UMFPACK_NDENSE_ROW] = nrow_elements ; + } + + DEBUG1 (("Symbolic usage: "ID" = head "ID" + tail "ID" after els\n", + head_usage + tail_usage, head_usage, tail_usage)) ; + + /* compute the tuple lengths */ + if (Esize) + { + /* row tuples */ + for (row = n1 ; row < n_row ; row++) + { + rdeg = Rdeg [row] ; + tlen = (rdeg > dense_row_threshold) ? 1 : rdeg ; + tail_usage += 1 + UNITS (Tuple, TUPLES (tlen)) ; + dtail_usage += 1 + DUNITS (Tuple, TUPLES (tlen)) ; + } + /* column tuples */ + for (col = n1 ; col < n_col - nempty_col ; col++) + { + /* tlen is 1 plus the number of dense rows in this column */ + esize = Esize [col - n1] ; + tlen = (esize > 0) + (Cdeg [col] - esize) ; + tail_usage += 1 + UNITS (Tuple, TUPLES (tlen)) ; + dtail_usage += 1 + DUNITS (Tuple, TUPLES (tlen)) ; + } + for ( ; col < n_col ; col++) + { + tail_usage += 1 + UNITS (Tuple, TUPLES (0)) ; + dtail_usage += 1 + DUNITS (Tuple, TUPLES (0)) ; + } + } + else + { + /* row tuples */ + for (row = n1 ; row < n_row ; row++) + { + tlen = Rdeg [row] ; + tail_usage += 1 + UNITS (Tuple, TUPLES (tlen)) ; + dtail_usage += 1 + DUNITS (Tuple, TUPLES (tlen)) ; + } + /* column tuples */ + for (col = n1 ; col < n_col ; col++) + { + tail_usage += 1 + UNITS (Tuple, TUPLES (1)) ; + dtail_usage += 1 + DUNITS (Tuple, TUPLES (1)) ; + } + } + + Symbolic->num_mem_init_usage = head_usage + tail_usage ; + DEBUG1 (("Symbolic usage: "ID" = head "ID" + tail "ID" final\n", + Symbolic->num_mem_init_usage, head_usage, tail_usage)) ; + + ASSERT (UMF_is_permutation (Rperm_init, Ci, n_row, n_row)) ; + + /* initial head and tail usage in Numeric->Memory */ + dmax_usage = dhead_usage + dtail_usage ; + dmax_usage = MAX (Symbolic->num_mem_init_usage, ceil (dmax_usage)) ; + Info [UMFPACK_VARIABLE_INIT_ESTIMATE] = dmax_usage ; + + /* In case Symbolic->num_mem_init_usage overflows, keep as a double, too */ + Symbolic->dnum_mem_init_usage = dmax_usage ; + + /* free the Rpi and Rpx workspace */ + tail_usage -= UNITS (Int *, n_row+1) + UNITS (Entry *, n_row+1) ; + dtail_usage -= DUNITS (Int *, n_row+1) + DUNITS (Entry *, n_row+1) ; + + /* ---------------------------------------------------------------------- */ + /* simulate UMF_kernel, assuming unsymmetric pivoting */ + /* ---------------------------------------------------------------------- */ + + /* Use Ci as temporary workspace for link lists [ */ + Link = Ci ; + for (i = 0 ; i < nfr ; i++) + { + Link [i] = EMPTY ; + } + + flops = 0 ; /* flop count upper bound */ + + for (chain = 0 ; chain < nchains ; chain++) + { + double fsize ; + f1 = Chain_start [chain] ; + f2 = Chain_start [chain+1] - 1 ; + + /* allocate frontal matrix working array (C, L, and U) */ + dr = Chain_maxrows [chain] ; + dc = Chain_maxcols [chain] ; + fsize = + nb*nb /* LU is nb-by-nb */ + + dr*nb /* L is dr-by-nb */ + + nb*dc /* U is nb-by-dc, stored by rows */ + + dr*dc ; /* C is dr by dc */ + dtail_usage += DUNITS (Entry, fsize) ; + dmax_usage = MAX (dmax_usage, dhead_usage + dtail_usage) ; + + for (i = f1 ; i <= f2 ; i++) + { + + /* get frontal matrix info */ + fpivcol = Front_npivcol [i] ; /* # candidate pivot columns */ + fallrows = Fr_nrows [i] ; /* all rows (not just Schur comp*/ + fallcols = Fr_ncols [i] ; /* all cols (not just Schur comp*/ + parent = Front_parent [i] ; /* parent in column etree */ + fpiv = MIN (fpivcol, fallrows) ; /* # pivot rows and cols */ + f = (double) fpiv ; + r = fallrows - fpiv ; /* # rows in Schur comp. */ + c = fallcols - fpiv ; /* # cols in Schur comp. */ + + /* assemble all children of front i in column etree */ + for (child = Link [i] ; child != EMPTY ; child = Link [child]) + { + ASSERT (child >= 0 && child < i) ; + ASSERT (Front_parent [child] == i) ; + /* free the child element and remove it from tuple lists */ + cp = MIN (Front_npivcol [child], Fr_nrows [child]) ; + cr = Fr_nrows [child] - cp ; + cc = Fr_ncols [child] - cp ; + ASSERT (cp >= 0 && cr >= 0 && cc >= 0) ; + dtail_usage -= ELEMENT_SIZE (cr, cc) ; + + } + + /* The flop count computed here is "canonical". */ + + /* factorize the frontal matrix */ + flops += DIV_FLOPS * (f*r + (f-1)*f/2) /* scale pivot columns */ + /* f outer products: */ + + MULTSUB_FLOPS * (f*r*c + (r+c)*(f-1)*f/2 + (f-1)*f*(2*f-1)/6); + + /* count nonzeros and memory usage in double precision */ + dlf = (f*f-f)/2 + f*r ; /* nz in L below diagonal */ + duf = (f*f-f)/2 + f*c ; /* nz in U above diagonal */ + dlnz += dlf ; + dunz += duf ; + + /* store f columns of L and f rows of U */ + dhead_usage += + DUNITS (Entry, dlf + duf) /* numerical values (excl diag) */ + + DUNITS (Int, r + c + f) ; /* indices (compressed) */ + + if (parent != EMPTY) + { + /* create new element and place in tuple lists */ + dtail_usage += ELEMENT_SIZE (r, c) ; + + /* place in link list of parent */ + Link [i] = Link [parent] ; + Link [parent] = i ; + } + + /* keep track of peak Numeric->Memory usage */ + dmax_usage = MAX (dmax_usage, dhead_usage + dtail_usage) ; + + } + + /* free the current frontal matrix */ + dtail_usage -= DUNITS (Entry, fsize) ; + } + + dhead_usage = ceil (dhead_usage) ; + dmax_usage = ceil (dmax_usage) ; + Symbolic->num_mem_size_est = dhead_usage ; + Symbolic->num_mem_usage_est = dmax_usage ; + Symbolic->lunz_bound = dlnz + dunz - n_inner ; + + /* ] done using Ci as workspace for Link array */ + + /* ---------------------------------------------------------------------- */ + /* estimate total memory usage in UMFPACK_numeric */ + /* ---------------------------------------------------------------------- */ + + UMF_set_stats ( + Info, + Symbolic, + dmax_usage, /* estimated peak size of Numeric->Memory */ + dhead_usage, /* estimated final size of Numeric->Memory */ + flops, /* estimated "true flops" */ + dlnz, /* estimated nz in L */ + dunz, /* estimated nz in U */ + dmaxfrsize, /* estimated largest front size */ + (double) n_col, /* worst case Numeric->Upattern size */ + (double) n_inner, /* max possible pivots to be found */ + (double) maxnrows, /* estimated largest #rows in front */ + (double) maxncols, /* estimated largest #cols in front */ + TRUE, /* assume scaling is to be performed */ + prefer_diagonal, + ESTIMATE) ; + + /* ---------------------------------------------------------------------- */ + +#ifndef NDEBUG + for (i = 0 ; i < nchains ; i++) + { + DEBUG2 (("Chain "ID" start "ID" end "ID" maxrows "ID" maxcols "ID"\n", + i, Chain_start [i], Chain_start [i+1] - 1, + Chain_maxrows [i], Chain_maxcols [i])) ; + UMF_dump_chain (Chain_start [i], Fr_parent, Fr_npivcol, Fr_nrows, + Fr_ncols, nfr) ; + } + fpivcol = 0 ; + for (i = 0 ; i < nfr ; i++) + { + fpivcol = MAX (fpivcol, Front_npivcol [i]) ; + } + DEBUG0 (("Max pivot cols in any front: "ID"\n", fpivcol)) ; + DEBUG1 (("Largest front: maxnrows "ID" maxncols "ID" dmaxfrsize %g\n", + maxnrows, maxncols, dmaxfrsize)) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* UMFPACK_symbolic was successful, return the object handle */ + /* ---------------------------------------------------------------------- */ + + Symbolic->valid = SYMBOLIC_VALID ; + *SymbolicHandle = (void *) Symbolic ; + + /* ---------------------------------------------------------------------- */ + /* free workspace */ + /* ---------------------------------------------------------------------- */ + + /* (6) The last of the workspace is free'd. The final Symbolic object + * consists of 12 to 14 allocated objects. Its final total size is lies + * roughly between 4*n and 13*n for a square matrix, which is all that is + * left of the memory allocated by this routine. If an error occurs, the + * entire Symbolic object is free'd when this routine returns (the error + * return routine, below). + */ + + free_work (SW) ; + + DEBUG0 (("(3)Symbolic UMF_malloc_count - init_count = "ID"\n", + UMF_malloc_count - init_count)) ; + ASSERT (UMF_malloc_count == init_count + 12 + + (Symbolic->Esize != (Int *) NULL) + + (Symbolic->Diagonal_map != (Int *) NULL)) ; + + /* ---------------------------------------------------------------------- */ + /* get the time used by UMFPACK_*symbolic */ + /* ---------------------------------------------------------------------- */ + + umfpack_toc (stats) ; + Info [UMFPACK_SYMBOLIC_WALLTIME] = stats [0] ; + Info [UMFPACK_SYMBOLIC_TIME] = stats [1] ; + + return (UMFPACK_OK) ; +} + + +/* ========================================================================== */ +/* === free_work ============================================================ */ +/* ========================================================================== */ + +PRIVATE void free_work +( + SWType *SW +) +{ + if (SW) + { + SW->Rperm_2by2 = (Int *) UMF_free ((void *) SW->Rperm_2by2) ; + SW->InvRperm1 = (Int *) UMF_free ((void *) SW->InvRperm1) ; + SW->Rs = (double *) UMF_free ((void *) SW->Rs) ; + SW->Si = (Int *) UMF_free ((void *) SW->Si) ; + SW->Sp = (Int *) UMF_free ((void *) SW->Sp) ; + SW->Ci = (Int *) UMF_free ((void *) SW->Ci) ; + SW->Front_npivcol = (Int *) UMF_free ((void *) SW->Front_npivcol); + SW->Front_nrows = (Int *) UMF_free ((void *) SW->Front_nrows) ; + SW->Front_ncols = (Int *) UMF_free ((void *) SW->Front_ncols) ; + SW->Front_parent = (Int *) UMF_free ((void *) SW->Front_parent) ; + SW->Front_cols = (Int *) UMF_free ((void *) SW->Front_cols) ; + SW->Cperm1 = (Int *) UMF_free ((void *) SW->Cperm1) ; + SW->Rperm1 = (Int *) UMF_free ((void *) SW->Rperm1) ; + SW->InFront = (Int *) UMF_free ((void *) SW->InFront) ; + } +} + + +/* ========================================================================== */ +/* === error ================================================================ */ +/* ========================================================================== */ + +/* Error return from UMFPACK_symbolic. Free all allocated memory. */ + +PRIVATE void error +( + SymbolicType **Symbolic, + SWType *SW +) +{ + + free_work (SW) ; + UMFPACK_free_symbolic ((void **) Symbolic) ; + ASSERT (UMF_malloc_count == init_count) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_control.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_control.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_control.c @@ -0,0 +1,386 @@ +/* ========================================================================== */ +/* === UMFPACK_report_control =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints the control settings. See umfpack_report_control.h + for details. +*/ + +#include "umf_internal.h" + +GLOBAL void UMFPACK_report_control +( + const double Control [UMFPACK_CONTROL] +) +{ + double drow, dcol, relpt, relpt2, alloc_init, front_alloc_init, amd_alpha, + tol, force_fixQ, droptol, aggr ; + Int prl, nb, irstep, strategy, scale, s ; + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl < 2) + { + /* default is to print nothing */ + return ; + } + + PRINTF (("\n%s, Control:\n\n", UMFPACK_VERSION)) ; + + /* ---------------------------------------------------------------------- */ + /* run-time options */ + /* ---------------------------------------------------------------------- */ + + /* This is a "run-time" option because all four umfpack_* versions */ + /* compiled into the UMFPACK library. */ + +#ifdef DINT + PRINTF ((" Matrix entry defined as: double\n")) ; + PRINTF ((" Int (generic integer) defined as: int\n")) ; +#endif +#ifdef DLONG + PRINTF ((" Matrix entry defined as: double\n")) ; + PRINTF ((" Int (generic integer) defined as: long\n")) ; +#endif +#ifdef ZINT + PRINTF ((" Matrix entry defined as: double complex\n")) ; + PRINTF ((" Int (generic integer) defined as: int\n")) ; +#endif +#ifdef ZLONG + PRINTF ((" Matrix entry defined as: double complex\n")) ; + PRINTF ((" Int (generic integer) defined as: long\n")) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* printing level */ + /* ---------------------------------------------------------------------- */ + + PRINTF (("\n "ID": print level: "ID"\n", + (Int) INDEX (UMFPACK_PRL), prl)) ; + + /* ---------------------------------------------------------------------- */ + /* dense row/col parameters */ + /* ---------------------------------------------------------------------- */ + + drow = GET_CONTROL (UMFPACK_DENSE_ROW, UMFPACK_DEFAULT_DENSE_ROW) ; + dcol = GET_CONTROL (UMFPACK_DENSE_COL, UMFPACK_DEFAULT_DENSE_COL) ; + + PRINTF ((" "ID": dense row parameter: %g\n", + (Int) INDEX (UMFPACK_DENSE_ROW), drow)) ; + PRINTF ((" \"dense\" rows have > max (16, (%g)*16*sqrt(n_col)" + " entries)\n", drow)) ; + PRINTF ((" "ID": dense column parameter: %g\n", + (Int) INDEX (UMFPACK_DENSE_COL), dcol)) ; + PRINTF ((" \"dense\" columns have > max (16, (%g)*16*sqrt(n_row)" + " entries)\n", dcol)) ; + + /* ---------------------------------------------------------------------- */ + /* pivot tolerance */ + /* ---------------------------------------------------------------------- */ + + relpt = GET_CONTROL (UMFPACK_PIVOT_TOLERANCE, + UMFPACK_DEFAULT_PIVOT_TOLERANCE) ; + relpt = MAX (0.0, MIN (relpt, 1.0)) ; + PRINTF ((" "ID": pivot tolerance: %g\n", + (Int) INDEX (UMFPACK_PIVOT_TOLERANCE), relpt)) ; + + /* ---------------------------------------------------------------------- */ + /* block size */ + /* ---------------------------------------------------------------------- */ + + nb = GET_CONTROL (UMFPACK_BLOCK_SIZE, UMFPACK_DEFAULT_BLOCK_SIZE) ; + nb = MAX (1, nb) ; + PRINTF ((" "ID": block size for dense matrix kernels: "ID"\n", + (Int) INDEX (UMFPACK_BLOCK_SIZE), nb)) ; + + /* ---------------------------------------------------------------------- */ + /* strategy */ + /* ---------------------------------------------------------------------- */ + + strategy = GET_CONTROL (UMFPACK_STRATEGY, UMFPACK_DEFAULT_STRATEGY) ; + if (strategy < UMFPACK_STRATEGY_AUTO + || strategy > UMFPACK_STRATEGY_SYMMETRIC) + { + strategy = UMFPACK_STRATEGY_AUTO ; + } + + PRINTF ((" "ID": strategy: "ID, + (Int) INDEX (UMFPACK_STRATEGY), strategy)) ; + + if (strategy == UMFPACK_STRATEGY_SYMMETRIC) + { + PRINTF ((" (symmetric)\n" + " Q = AMD (A+A'), Q not refined during numerical\n" + " factorization, and diagonal pivoting (P=Q') attempted.\n")) ; + } + else if (strategy == UMFPACK_STRATEGY_UNSYMMETRIC) + { + PRINTF ((" (unsymmetric)\n" + " Q = COLAMD (A), Q refined during numerical\n" + " factorization, and no attempt at diagonal pivoting.\n")) ; + } + else if (strategy == UMFPACK_STRATEGY_2BY2) + { + PRINTF ((" (symmetric, with 2-by-2 block pivoting)\n" + " P2 = row permutation that tries to place large entries on\n" + " the diagonal. Q = AMD (P2*A+(P2*A)'), Q not refined during\n" + " numerical factorization, attempt to select pivots from the\n" + " diagonal of P2*A.\n")) ; + } + else /* auto strategy */ + { + strategy = UMFPACK_STRATEGY_AUTO ; + PRINTF ((" (auto)\n")) ; + } + + /* ---------------------------------------------------------------------- */ + /* initial allocation parameter */ + /* ---------------------------------------------------------------------- */ + + alloc_init = GET_CONTROL (UMFPACK_ALLOC_INIT, UMFPACK_DEFAULT_ALLOC_INIT) ; + if (alloc_init >= 0) + { + PRINTF ((" "ID": initial allocation ratio: %g\n", + (Int) INDEX (UMFPACK_ALLOC_INIT), alloc_init)) ; + } + else + { + s = -alloc_init ; + s = MAX (1, s) ; + PRINTF ((" "ID": initial allocation (in Units): "ID"\n", + (Int) INDEX (UMFPACK_ALLOC_INIT), s)) ; + } + + /* ---------------------------------------------------------------------- */ + /* maximum iterative refinement steps */ + /* ---------------------------------------------------------------------- */ + + irstep = GET_CONTROL (UMFPACK_IRSTEP, UMFPACK_DEFAULT_IRSTEP) ; + irstep = MAX (0, irstep) ; + PRINTF ((" "ID": max iterative refinement steps: "ID"\n", + (Int) INDEX (UMFPACK_IRSTEP), irstep)) ; + + /* ---------------------------------------------------------------------- */ + /* 2-by-2 pivot tolerance */ + /* ---------------------------------------------------------------------- */ + + tol = GET_CONTROL (UMFPACK_2BY2_TOLERANCE, UMFPACK_DEFAULT_2BY2_TOLERANCE) ; + tol = MAX (0.0, MIN (tol, 1.0)) ; + PRINTF ((" "ID": 2-by-2 pivot tolerance: %g\n", + (Int) INDEX (UMFPACK_2BY2_TOLERANCE), tol)) ; + + /* ---------------------------------------------------------------------- */ + /* force fixQ */ + /* ---------------------------------------------------------------------- */ + + force_fixQ = GET_CONTROL (UMFPACK_FIXQ, UMFPACK_DEFAULT_FIXQ) ; + PRINTF ((" "ID": Q fixed during numerical factorization: %g ", + (Int) INDEX (UMFPACK_FIXQ), force_fixQ)) ; + if (force_fixQ > 0) + { + PRINTF (("(yes)\n")) ; + } + else if (force_fixQ < 0) + { + PRINTF (("(no)\n")) ; + } + else + { + PRINTF (("(auto)\n")) ; + } + + /* ---------------------------------------------------------------------- */ + /* AMD parameters */ + /* ---------------------------------------------------------------------- */ + + amd_alpha = GET_CONTROL (UMFPACK_AMD_DENSE, UMFPACK_DEFAULT_AMD_DENSE) ; + PRINTF ((" "ID": AMD dense row/col parameter: %g\n", + (Int) INDEX (UMFPACK_AMD_DENSE), amd_alpha)) ; + if (amd_alpha < 0) + { + PRINTF ((" no \"dense\" rows/columns\n")) ; + } + else + { + PRINTF ((" \"dense\" rows/columns have > max (16, (%g)*sqrt(n))" + " entries\n", amd_alpha)) ; + } + PRINTF ((" Only used if the AMD ordering is used.\n")) ; + + /* ---------------------------------------------------------------------- */ + /* pivot tolerance for symmetric pivoting */ + /* ---------------------------------------------------------------------- */ + + relpt2 = GET_CONTROL (UMFPACK_SYM_PIVOT_TOLERANCE, + UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE) ; + relpt2 = MAX (0.0, MIN (relpt2, 1.0)) ; + PRINTF ((" "ID": diagonal pivot tolerance: %g\n" + " Only used if diagonal pivoting is attempted.\n", + (Int) INDEX (UMFPACK_SYM_PIVOT_TOLERANCE), relpt2)) ; + + /* ---------------------------------------------------------------------- */ + /* scaling */ + /* ---------------------------------------------------------------------- */ + + scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ; + if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX) + { + scale = UMFPACK_DEFAULT_SCALE ; + } + PRINTF ((" "ID": scaling: "ID, (Int) INDEX (UMFPACK_SCALE), scale)) ; + if (scale == UMFPACK_SCALE_NONE) + { + PRINTF ((" (no)")) ; + } + else if (scale == UMFPACK_SCALE_SUM) + { + PRINTF ((" (divide each row by sum of abs. values in each row)")) ; + } + else if (scale == UMFPACK_SCALE_MAX) + { + PRINTF ((" (divide each row by max. abs. value in each row)")) ; + } + PRINTF (("\n")) ; + + /* ---------------------------------------------------------------------- */ + /* frontal matrix allocation parameter */ + /* ---------------------------------------------------------------------- */ + + front_alloc_init = GET_CONTROL (UMFPACK_FRONT_ALLOC_INIT, + UMFPACK_DEFAULT_FRONT_ALLOC_INIT) ; + front_alloc_init = MIN (1.0, front_alloc_init) ; + if (front_alloc_init >= 0) + { + PRINTF ((" "ID": frontal matrix allocation ratio: %g\n", + (Int) INDEX (UMFPACK_FRONT_ALLOC_INIT), front_alloc_init)) ; + } + else + { + s = -front_alloc_init ; + s = MAX (1, s) ; + PRINTF ((" "ID": initial frontal matrix size (# of Entry's): "ID"\n", + (Int) INDEX (UMFPACK_FRONT_ALLOC_INIT), s)) ; + } + + /* ---------------------------------------------------------------------- */ + /* drop tolerance */ + /* ---------------------------------------------------------------------- */ + + droptol = GET_CONTROL (UMFPACK_DROPTOL, UMFPACK_DEFAULT_DROPTOL) ; + PRINTF ((" "ID": drop tolerance: %g\n", + (Int) INDEX (UMFPACK_DROPTOL), droptol)) ; + + /* ---------------------------------------------------------------------- */ + /* aggressive absorption */ + /* ---------------------------------------------------------------------- */ + + aggr = GET_CONTROL (UMFPACK_AGGRESSIVE, UMFPACK_DEFAULT_AGGRESSIVE) ; + PRINTF ((" "ID": AMD and COLAMD aggressive absorption: %g", + (Int) INDEX (UMFPACK_AGGRESSIVE), aggr)) ; + if (aggr != 0.0) + { + PRINTF ((" (yes)\n")) ; + } + else + { + PRINTF ((" (no)\n")) ; + } + + /* ---------------------------------------------------------------------- */ + /* compile-time options */ + /* ---------------------------------------------------------------------- */ + + PRINTF (( + "\n The following options can only be changed at compile-time:\n")) ; + + PRINTF ((" "ID": BLAS library used: ", + (Int) INDEX (UMFPACK_COMPILED_WITH_BLAS))) ; + +#if defined (USE_NO_BLAS) + PRINTF (("none. UMFPACK will be slow.\n")) ; +#elif defined (USE_C_BLAS) + PRINTF (("C-BLAS.\n")) ; +#elif defined (USE_MATLAB_BLAS) + PRINTF (("built-in MATLAB BLAS (ATLAS).\n")) ; +#elif defined (USE_SUNPERF_BLAS) + PRINTF (("Sun Performance Library BLAS.\n")) ; +#elif defined (USE_SCSL_BLAS) + PRINTF (("SGI SCSL BLAS.\n")) ; +#elif defined (USE_FORTRAN_BLAS) + PRINTF (("Fortran BLAS.\n")) ; +#endif + +#ifdef MATLAB_MEX_FILE +#ifdef NUTIL + PRINTF ((" "ID": compiled for MATLAB" + " (uses mxMalloc, mxFree, mxRealloc, and mexPrintf)\n", + (Int) INDEX (UMFPACK_COMPILED_FOR_MATLAB))) ; +#else + PRINTF ((" "ID": compiled for MATLAB" + " (uses utMalloc, utFree, utRealloc, and mexPrintf)\n", + (Int) INDEX (UMFPACK_COMPILED_FOR_MATLAB))) ; +#endif +#else +#ifdef MATHWORKS + PRINTF ((" "ID": compiled for MATLAB, using internal utility routines\n" + " (uses utMalloc, utFree, utRealloc, and utPrintf)\n", + (Int) INDEX (UMFPACK_COMPILED_FOR_MATLAB))) ; + PRINTF ((" (complex version uses utDivideComplex, utFdlibm_hypot)\n")) ; +#else + PRINTF ((" "ID": compiled for ANSI C" + " (uses malloc, free, realloc, and printf)\n", + (Int) INDEX (UMFPACK_COMPILED_FOR_MATLAB))) ; +#endif +#endif + +#ifdef NO_TIMER + PRINTF ((" "ID": no CPU timer \n", + (Int) INDEX (UMFPACK_COMPILED_WITH_GETRUSAGE))) ; +#else +#ifndef NPOSIX + PRINTF ((" "ID": CPU timer is POSIX times ( ) routine.\n", + (Int) INDEX (UMFPACK_COMPILED_WITH_GETRUSAGE))) ; +#else +#ifdef GETRUSAGE + PRINTF ((" "ID": CPU timer is getrusage.\n", + (Int) INDEX (UMFPACK_COMPILED_WITH_GETRUSAGE))) ; +#else + PRINTF ((" "ID": CPU timer is ANSI C clock (may wrap around).\n", + (Int) INDEX (UMFPACK_COMPILED_WITH_GETRUSAGE))) ; +#endif +#endif +#endif + +#ifndef NDEBUG + PRINTF (( +"**** Debugging enabled (UMFPACK will be exceedingly slow!) *****************\n" +" "ID": compiled with debugging enabled. ", + (Int) INDEX (UMFPACK_COMPILED_IN_DEBUG_MODE))) ; +#ifdef MATLAB_MEX_FILE + PRINTF (("Uses mxAssert.\n")) ; +#else +#ifdef MATHWORKS + PRINTF (("Uses utAssert.\n")) ; +#else + PRINTF (("Uses ANSI C assert.\n")) ; +#endif +#endif +#else + PRINTF ((" "ID": compiled for normal operation (debugging disabled)\n", + (Int) INDEX (UMFPACK_COMPILED_IN_DEBUG_MODE))) ; +#endif + + PRINTF ((" computer/operating system: %s\n", UMFPACK_ARCHITECTURE)) ; + PRINTF ((" size of int: %g long: %g Int: %g pointer: %g" + " double: %g Entry: %g (in bytes)\n\n", (double) sizeof (int), + (double) sizeof (long), (double) sizeof (Int), + (double) sizeof (void *), (double) sizeof (double), + (double) sizeof (Entry))) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_info.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_info.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_info.c @@ -0,0 +1,615 @@ +/* ========================================================================== */ +/* === UMFPACK_report_info ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints the Info array. See umfpack_report_info.h for + details. +*/ + +#include "umf_internal.h" + +#define PRINT_INFO(format,x) \ +{ \ + if (SCALAR_IS_NAN (x) || (!SCALAR_IS_LTZERO (x))) \ + { \ + PRINTF ((format, x)) ; \ + } \ +} + +/* RATIO macro uses a double relop, but ignore NaN case: */ +#define RATIO(a,b,c) (((b) == 0) ? (c) : (((double) a)/((double) b))) + +/* ========================================================================== */ +/* === print_ratio ========================================================== */ +/* ========================================================================== */ + +PRIVATE void print_ratio +( + char *what, + char *format, + double estimate, + double actual +) +{ + if (estimate < 0 && actual < 0) /* double relop, but ignore Nan case */ + { + return ; + } + PRINTF ((" %-27s", what)) ; + if (estimate >= 0) /* double relop, but ignore Nan case */ + { + PRINTF ((format, estimate)) ; + } + else + { + PRINTF ((" -")) ; + } + if (actual >= 0) /* double relop, but ignore Nan case */ + { + PRINTF ((format, actual)) ; + } + else + { + PRINTF ((" -")) ; + } + if (estimate >= 0 && actual >= 0) /* double relop, but ignore Nan case */ + { + PRINTF ((" %5.0f%%\n", 100 * RATIO (actual, estimate, 1))) ; + } + else + { + PRINTF ((" -\n")) ; + } +} + +/* ========================================================================== */ +/* === UMFPACK_report_info ================================================== */ +/* ========================================================================== */ + +GLOBAL void UMFPACK_report_info +( + const double Control [UMFPACK_CONTROL], + const double Info [UMFPACK_INFO] +) +{ + + double lnz_est, unz_est, lunz_est, lnz, unz, lunz, tsym, tnum, fnum, tsolve, + fsolve, ttot, ftot, twsym, twnum, twsolve, twtot, n2 ; + Int n_row, n_col, n_inner, prl, is_sym ; + + /* ---------------------------------------------------------------------- */ + /* get control settings and status to determine what to print */ + /* ---------------------------------------------------------------------- */ + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (!Info || prl < 2) + { + /* no output generated if Info is (double *) NULL */ + /* or if prl is less than 2 */ + return ; + } + + /* ---------------------------------------------------------------------- */ + /* print umfpack version */ + /* ---------------------------------------------------------------------- */ + + PRINTF (("\n%s, Info:\n", UMFPACK_VERSION)) ; + +#ifndef NDEBUG + PRINTF (( +"**** Debugging enabled (UMFPACK will be exceedingly slow!) *****************\n" + )) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* print run-time options */ + /* ---------------------------------------------------------------------- */ + +#ifdef DINT + PRINTF ((" matrix entry defined as: double\n")) ; + PRINTF ((" Int (generic integer) defined as: int\n")) ; +#endif +#ifdef DLONG + PRINTF ((" matrix entry defined as: double\n")) ; + PRINTF ((" Int (generic integer) defined as: long\n")) ; +#endif +#ifdef ZINT + PRINTF ((" matrix entry defined as: double complex\n")) ; + PRINTF ((" Int (generic integer) defined as: int\n")) ; +#endif +#ifdef ZLONG + PRINTF ((" matrix entry defined as: double complex\n")) ; + PRINTF ((" Int (generic integer) defined as: long\n")) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* print compile-time options */ + /* ---------------------------------------------------------------------- */ + + PRINTF ((" BLAS library used: ")) ; + +#if defined (USE_NO_BLAS) + PRINTF (("none. UMFPACK will be slow.\n")) ; +#elif defined (USE_C_BLAS) + PRINTF (("C-BLAS.\n")) ; +#elif defined (USE_MATLAB_BLAS) + PRINTF (("built-in MATLAB BLAS.\n")) ; +#elif defined (USE_SUNPERF_BLAS) + PRINTF (("Sun Performance Library BLAS.\n")) ; +#elif defined (USE_SCSL_BLAS) + PRINTF (("SGI SCSL BLAS.\n")) ; +#elif defined (USE_FORTRAN_BLAS) + PRINTF (("Fortran BLAS.\n")) ; +#endif + + PRINTF ((" MATLAB: ")) ; +#ifdef MATLAB_MEX_FILE + PRINTF (("yes.\n")) ; +#else +#ifdef MATHWORKS + PRINTF (("yes (using internal ut* routines).\n")) ; +#else + PRINTF (("no.\n")) ; +#endif +#endif + + PRINTF ((" CPU timer: ")) ; +#ifdef NO_TIMER + PRINTF (("none.\n")) ; +#else +#ifndef NPOSIX + PRINTF (("POSIX times ( ) routine.\n")) ; +#else +#ifdef GETRUSAGE + PRINTF (("getrusage ( ) routine.\n")) ; +#else + PRINTF (("ANSI clock ( ) routine.\n")) ; +#endif +#endif +#endif + + /* ---------------------------------------------------------------------- */ + /* print n and nz */ + /* ---------------------------------------------------------------------- */ + + n_row = (Int) Info [UMFPACK_NROW] ; + n_col = (Int) Info [UMFPACK_NCOL] ; + n_inner = MIN (n_row, n_col) ; + + PRINT_INFO (" number of rows in matrix A: "ID"\n", n_row) ; + PRINT_INFO (" number of columns in matrix A: "ID"\n", n_col) ; + PRINT_INFO (" entries in matrix A: "ID"\n", + (Int) Info [UMFPACK_NZ]) ; + PRINT_INFO (" memory usage reported in: "ID"-byte Units\n", + (Int) Info [UMFPACK_SIZE_OF_UNIT]) ; + + PRINT_INFO (" size of int: "ID" bytes\n", + (Int) Info [UMFPACK_SIZE_OF_INT]) ; + PRINT_INFO (" size of long: "ID" bytes\n", + (Int) Info [UMFPACK_SIZE_OF_LONG]) ; + PRINT_INFO (" size of pointer: "ID" bytes\n", + (Int) Info [UMFPACK_SIZE_OF_POINTER]) ; + PRINT_INFO (" size of numerical entry: "ID" bytes\n", + (Int) Info [UMFPACK_SIZE_OF_ENTRY]) ; + + /* ---------------------------------------------------------------------- */ + /* symbolic parameters */ + /* ---------------------------------------------------------------------- */ + + if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_SYMMETRIC) + { + PRINTF (("\n strategy used: symmetric\n")) ; + } + else if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_UNSYMMETRIC) + { + PRINTF (("\n strategy used: unsymmetric\n")) ; + } + else if (Info [UMFPACK_STRATEGY_USED] == UMFPACK_STRATEGY_2BY2) + { + PRINTF (("\n strategy used: symmetric 2-by-2\n")); + } + + if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_AMD) + { + PRINTF ((" ordering used: amd on A+A'\n")) ; + } + else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_COLAMD) + { + PRINTF ((" ordering used: colamd on A\n")) ; + } + else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_GIVEN) + { + PRINTF ((" ordering used: provided by user\n")) ; + } + + if (Info [UMFPACK_QFIXED] == 1) + { + PRINTF ((" modify Q during factorization: no\n")) ; + } + else if (Info [UMFPACK_QFIXED] == 0) + { + PRINTF ((" modify Q during factorization: yes\n")) ; + } + + if (Info [UMFPACK_DIAG_PREFERRED] == 0) + { + PRINTF ((" prefer diagonal pivoting: no\n")) ; + } + else if (Info [UMFPACK_DIAG_PREFERRED] == 1) + { + PRINTF ((" prefer diagonal pivoting: yes\n")) ; + } + + /* ---------------------------------------------------------------------- */ + /* singleton statistics */ + /* ---------------------------------------------------------------------- */ + + PRINT_INFO (" pivots with zero Markowitz cost: %0.f\n", + Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS]) ; + PRINT_INFO (" submatrix S after removing zero-cost pivots:\n" + " number of \"dense\" rows: %.0f\n", + Info [UMFPACK_NDENSE_ROW]) ; + PRINT_INFO (" number of \"dense\" columns: %.0f\n", + Info [UMFPACK_NDENSE_COL]) ; + PRINT_INFO (" number of empty rows: %.0f\n", + Info [UMFPACK_NEMPTY_ROW]) ; + PRINT_INFO (" number of empty columns %.0f\n", + Info [UMFPACK_NEMPTY_COL]) ; + is_sym = Info [UMFPACK_S_SYMMETRIC] ; + if (is_sym > 0) + { + PRINTF ((" submatrix S square and diagonal preserved\n")) ; + } + else if (is_sym == 0) + { + PRINTF ((" submatrix S not square or diagonal not preserved\n")); + } + + /* ---------------------------------------------------------------------- */ + /* statistics from amd_aat */ + /* ---------------------------------------------------------------------- */ + + n2 = Info [UMFPACK_N2] ; + if (n2 >= 0) + { + PRINTF ((" pattern of square submatrix S:\n")) ; + } + PRINT_INFO (" number rows and columns %.0f\n", + n2) ; + PRINT_INFO (" symmetry of nonzero pattern: %.6f\n", + Info [UMFPACK_PATTERN_SYMMETRY]) ; + PRINT_INFO (" nz in S+S' (excl. diagonal): %.0f\n", + Info [UMFPACK_NZ_A_PLUS_AT]) ; + PRINT_INFO (" nz on diagonal of matrix S: %.0f\n", + Info [UMFPACK_NZDIAG]) ; + if (Info [UMFPACK_NZDIAG] >= 0 && n2 > 0) + { + PRINTF ((" fraction of nz on diagonal: %.6f\n", + Info [UMFPACK_NZDIAG] / n2)) ; + } + + /* ---------------------------------------------------------------------- */ + /* statistics from 2-by-2 permutation */ + /* ---------------------------------------------------------------------- */ + + PRINT_INFO (" 2-by-2 pivoting to place large entries on diagonal:\n" + " # of small diagonal entries of S: %.0f\n", + Info [UMFPACK_2BY2_NWEAK]) ; + PRINT_INFO (" # unmatched: %.0f\n", + Info [UMFPACK_2BY2_UNMATCHED]) ; + PRINT_INFO (" symmetry of P2*S: %.6f\n", + Info [UMFPACK_2BY2_PATTERN_SYMMETRY]) ; + PRINT_INFO (" nz in P2*S+(P2*S)' (excl. diag.): %.0f\n", + Info [UMFPACK_2BY2_NZ_PA_PLUS_PAT]) ; + PRINT_INFO (" nz on diagonal of P2*S: %.0f\n", + Info [UMFPACK_2BY2_NZDIAG]) ; + if (Info [UMFPACK_2BY2_NZDIAG] >= 0 && n2 > 0) + { + PRINTF ((" fraction of nz on diag of P2*S: %.6f\n", + Info [UMFPACK_2BY2_NZDIAG] / n2)) ; + } + + /* ---------------------------------------------------------------------- */ + /* statistics from AMD */ + /* ---------------------------------------------------------------------- */ + + if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_AMD) + { + double dmax = Info [UMFPACK_SYMMETRIC_DMAX] ; + PRINTF ((" AMD statistics, for strict diagonal pivoting:\n")) ; + PRINT_INFO (" est. flops for LU factorization: %.5e\n", + Info [UMFPACK_SYMMETRIC_FLOPS]) ; + PRINT_INFO (" est. nz in L+U (incl. diagonal): %.0f\n", + Info [UMFPACK_SYMMETRIC_LUNZ]) ; + PRINT_INFO (" est. largest front (# entries): %.0f\n", + dmax*dmax) ; + PRINT_INFO (" est. max nz in any column of L: %.0f\n", + dmax) ; + PRINT_INFO ( + " number of \"dense\" rows/columns in S+S': %.0f\n", + Info [UMFPACK_SYMMETRIC_NDENSE]) ; + } + + /* ---------------------------------------------------------------------- */ + /* symbolic factorization */ + /* ---------------------------------------------------------------------- */ + + tsym = Info [UMFPACK_SYMBOLIC_TIME] ; + twsym = Info [UMFPACK_SYMBOLIC_WALLTIME] ; + + PRINT_INFO (" symbolic factorization defragmentations: %.0f\n", + Info [UMFPACK_SYMBOLIC_DEFRAG]) ; + PRINT_INFO (" symbolic memory usage (Units): %.0f\n", + Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]) ; + PRINT_INFO (" symbolic memory usage (MBytes): %.1f\n", + MBYTES (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY])) ; + PRINT_INFO (" Symbolic size (Units): %.0f\n", + Info [UMFPACK_SYMBOLIC_SIZE]) ; + PRINT_INFO (" Symbolic size (MBytes): %.0f\n", + MBYTES (Info [UMFPACK_SYMBOLIC_SIZE])) ; + PRINT_INFO (" symbolic factorization CPU time (sec): %.2f\n", + tsym) ; + PRINT_INFO (" symbolic factorization wallclock time(sec): %.2f\n", + twsym) ; + + /* ---------------------------------------------------------------------- */ + /* scaling, from numerical factorization */ + /* ---------------------------------------------------------------------- */ + + if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_NONE) + { + PRINTF (("\n matrix scaled: no\n")) ; + } + else if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_SUM) + { + PRINTF (("\n matrix scaled: yes ")) ; + PRINTF (("(divided each row by sum of abs values in each row)\n")) ; + PRINTF ((" minimum sum (abs (rows of A)): %.5e\n", + Info [UMFPACK_RSMIN])) ; + PRINTF ((" maximum sum (abs (rows of A)): %.5e\n", + Info [UMFPACK_RSMAX])) ; + } + else if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_MAX) + { + PRINTF (("\n matrix scaled: yes ")) ; + PRINTF (("(divided each row by max abs value in each row)\n")) ; + PRINTF ((" minimum max (abs (rows of A)): %.5e\n", + Info [UMFPACK_RSMIN])) ; + PRINTF ((" maximum max (abs (rows of A)): %.5e\n", + Info [UMFPACK_RSMAX])) ; + } + + /* ---------------------------------------------------------------------- */ + /* estimate/actual in symbolic/numeric factorization */ + /* ---------------------------------------------------------------------- */ + + /* double relop, but ignore NaN case: */ + if (Info [UMFPACK_SYMBOLIC_DEFRAG] >= 0 /* UMFPACK_*symbolic called */ + || Info [UMFPACK_NUMERIC_DEFRAG] >= 0) /* UMFPACK_numeric called */ + { + PRINTF (("\n symbolic/numeric factorization: upper bound")) ; + PRINTF ((" actual %%\n")) ; + PRINTF ((" variable-sized part of Numeric object:\n")) ; + } + print_ratio (" initial size (Units)", " %20.0f", + Info [UMFPACK_VARIABLE_INIT_ESTIMATE], Info [UMFPACK_VARIABLE_INIT]) ; + print_ratio (" peak size (Units)", " %20.0f", + Info [UMFPACK_VARIABLE_PEAK_ESTIMATE], Info [UMFPACK_VARIABLE_PEAK]) ; + print_ratio (" final size (Units)", " %20.0f", + Info [UMFPACK_VARIABLE_FINAL_ESTIMATE], Info [UMFPACK_VARIABLE_FINAL]) ; + print_ratio ("Numeric final size (Units)", " %20.0f", + Info [UMFPACK_NUMERIC_SIZE_ESTIMATE], Info [UMFPACK_NUMERIC_SIZE]) ; + print_ratio ("Numeric final size (MBytes)", " %20.1f", + MBYTES (Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]), + MBYTES (Info [UMFPACK_NUMERIC_SIZE])) ; + print_ratio ("peak memory usage (Units)", " %20.0f", + Info [UMFPACK_PEAK_MEMORY_ESTIMATE], Info [UMFPACK_PEAK_MEMORY]) ; + print_ratio ("peak memory usage (MBytes)", " %20.1f", + MBYTES (Info [UMFPACK_PEAK_MEMORY_ESTIMATE]), + MBYTES (Info [UMFPACK_PEAK_MEMORY])) ; + print_ratio ("numeric factorization flops", " %20.5e", + Info [UMFPACK_FLOPS_ESTIMATE], Info [UMFPACK_FLOPS]) ; + + lnz_est = Info [UMFPACK_LNZ_ESTIMATE] ; + unz_est = Info [UMFPACK_UNZ_ESTIMATE] ; + if (lnz_est >= 0 && unz_est >= 0) /* double relop, but ignore NaN case */ + { + lunz_est = lnz_est + unz_est - n_inner ; + } + else + { + lunz_est = EMPTY ; + } + lnz = Info [UMFPACK_LNZ] ; + unz = Info [UMFPACK_UNZ] ; + if (lnz >= 0 && unz >= 0) /* double relop, but ignore NaN case */ + { + lunz = lnz + unz - n_inner ; + } + else + { + lunz = EMPTY ; + } + print_ratio ("nz in L (incl diagonal)", " %20.0f", lnz_est, lnz) ; + print_ratio ("nz in U (incl diagonal)", " %20.0f", unz_est, unz) ; + print_ratio ("nz in L+U (incl diagonal)", " %20.0f", lunz_est, lunz) ; + + print_ratio ("largest front (# entries)", " %20.0f", + Info [UMFPACK_MAX_FRONT_SIZE_ESTIMATE], Info [UMFPACK_MAX_FRONT_SIZE]) ; + print_ratio ("largest # rows in front", " %20.0f", + Info [UMFPACK_MAX_FRONT_NROWS_ESTIMATE], + Info [UMFPACK_MAX_FRONT_NROWS]) ; + print_ratio ("largest # columns in front", " %20.0f", + Info [UMFPACK_MAX_FRONT_NCOLS_ESTIMATE], + Info [UMFPACK_MAX_FRONT_NCOLS]) ; + + /* ---------------------------------------------------------------------- */ + /* numeric factorization */ + /* ---------------------------------------------------------------------- */ + + tnum = Info [UMFPACK_NUMERIC_TIME] ; + twnum = Info [UMFPACK_NUMERIC_WALLTIME] ; + fnum = Info [UMFPACK_FLOPS] ; + + PRINT_INFO ("\n initial allocation ratio used: %0.3g\n", + Info [UMFPACK_ALLOC_INIT_USED]) ; + PRINT_INFO (" # of forced updates due to frontal growth: %.0f\n", + Info [UMFPACK_FORCED_UPDATES]) ; + PRINT_INFO (" number of off-diagonal pivots: %.0f\n", + Info [UMFPACK_NOFF_DIAG]) ; + PRINT_INFO (" nz in L (incl diagonal), if none dropped %.0f\n", + Info [UMFPACK_ALL_LNZ]) ; + PRINT_INFO (" nz in U (incl diagonal), if none dropped %.0f\n", + Info [UMFPACK_ALL_UNZ]) ; + PRINT_INFO (" number of small entries dropped %.0f\n", + Info [UMFPACK_NZDROPPED]) ; + PRINT_INFO (" nonzeros on diagonal of U: %.0f\n", + Info [UMFPACK_UDIAG_NZ]) ; + PRINT_INFO (" min abs. value on diagonal of U: %.2e\n", + Info [UMFPACK_UMIN]) ; + PRINT_INFO (" max abs. value on diagonal of U: %.2e\n", + Info [UMFPACK_UMAX]) ; + PRINT_INFO (" estimate of reciprocal of condition number: %.2e\n", + Info [UMFPACK_RCOND]) ; + PRINT_INFO (" indices in compressed pattern: %.0f\n", + Info [UMFPACK_COMPRESSED_PATTERN]) ; + PRINT_INFO (" numerical values stored in Numeric object: %.0f\n", + Info [UMFPACK_LU_ENTRIES]) ; + PRINT_INFO (" numeric factorization defragmentations: %.0f\n", + Info [UMFPACK_NUMERIC_DEFRAG]) ; + PRINT_INFO (" numeric factorization reallocations: %.0f\n", + Info [UMFPACK_NUMERIC_REALLOC]) ; + PRINT_INFO (" costly numeric factorization reallocations: %.0f\n", + Info [UMFPACK_NUMERIC_COSTLY_REALLOC]) ; + PRINT_INFO (" numeric factorization CPU time (sec): %.2f\n", + tnum) ; + PRINT_INFO (" numeric factorization wallclock time (sec): %.2f\n", + twnum) ; + + if (tnum > 0 && fnum > 0) + { + PRINT_INFO ( + " numeric factorization mflops (CPU time): %.2f\n", + 1e-6 * fnum / tnum) ; + } + if (twnum > 0 && fnum > 0) + { + PRINT_INFO ( + " numeric factorization mflops (wallclock): %.2f\n", + 1e-6 * fnum / twnum) ; + } + + ttot = EMPTY ; + ftot = fnum ; + if (tsym >= 0 && tnum >= 0) + { + ttot = tsym + tnum ; + PRINT_INFO (" symbolic + numeric CPU time (sec): %.2f\n", + ttot) ; + if (ftot > 0 && ttot > 0) + { + PRINT_INFO ( + " symbolic + numeric mflops (CPU time): %.2f\n", + 1e-6 * ftot / ttot) ; + } + } + + twtot = EMPTY ; + if (twsym >= 0 && twnum >= 0) + { + twtot = twsym + twnum ; + PRINT_INFO (" symbolic + numeric wall clock time (sec): %.2f\n", + twtot) ; + if (ftot > 0 && twtot > 0) + { + PRINT_INFO ( + " symbolic + numeric mflops (wall clock): %.2f\n", + 1e-6 * ftot / twtot) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* solve */ + /* ---------------------------------------------------------------------- */ + + tsolve = Info [UMFPACK_SOLVE_TIME] ; + twsolve = Info [UMFPACK_SOLVE_WALLTIME] ; + fsolve = Info [UMFPACK_SOLVE_FLOPS] ; + + PRINT_INFO ("\n solve flops: %.5e\n", + fsolve) ; + PRINT_INFO (" iterative refinement steps taken: %.0f\n", + Info [UMFPACK_IR_TAKEN]) ; + PRINT_INFO (" iterative refinement steps attempted: %.0f\n", + Info [UMFPACK_IR_ATTEMPTED]) ; + PRINT_INFO (" sparse backward error omega1: %.2e\n", + Info [UMFPACK_OMEGA1]) ; + PRINT_INFO (" sparse backward error omega2: %.2e\n", + Info [UMFPACK_OMEGA2]) ; + PRINT_INFO (" solve CPU time (sec): %.2f\n", + tsolve) ; + PRINT_INFO (" solve wall clock time (sec): %.2f\n", + twsolve) ; + if (fsolve > 0 && tsolve > 0) + { + PRINT_INFO ( + " solve mflops (CPU time): %.2f\n", + 1e-6 * fsolve / tsolve) ; + } + if (fsolve > 0 && twsolve > 0) + { + PRINT_INFO ( + " solve mflops (wall clock time): %.2f\n", + 1e-6 * fsolve / twsolve) ; + } + + if (ftot >= 0 && fsolve >= 0) + { + ftot += fsolve ; + PRINT_INFO ( + "\n total symbolic + numeric + solve flops: %.5e\n", ftot) ; + } + + if (tsolve >= 0) + { + if (ttot >= 0 && ftot >= 0) + { + ttot += tsolve ; + PRINT_INFO ( + " total symbolic + numeric + solve CPU time: %.2f\n", + ttot) ; + if (ftot > 0 && ttot > 0) + { + PRINT_INFO ( + " total symbolic + numeric + solve mflops (CPU): %.2f\n", + 1e-6 * ftot / ttot) ; + } + } + } + + if (twsolve >= 0) + { + if (twtot >= 0 && ftot >= 0) + { + twtot += tsolve ; + PRINT_INFO ( + " total symbolic+numeric+solve wall clock time: %.2f\n", + twtot) ; + if (ftot > 0 && twtot > 0) + { + PRINT_INFO ( + " total symbolic+numeric+solve mflops(wallclock) %.2f\n", + 1e-6 * ftot / twtot) ; + } + } + } + PRINTF (("\n")) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_matrix.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_matrix.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_matrix.c @@ -0,0 +1,201 @@ +/* ========================================================================== */ +/* === UMFPACK_report_matrix ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints a column or row-oriented matrix. See + umfpack_report_matrix.h for details. +*/ + +#include "umf_internal.h" + +GLOBAL Int UMFPACK_report_matrix +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + Int col_form, /* 1: column form, 0: row form */ + const double Control [UMFPACK_CONTROL] +) +{ + Entry a ; + Int prl, i, k, length, ilast, p, nz, prl1, p1, p2, n, n_i, do_values ; + char *vector, *index ; +#ifdef COMPLEX + Int split = SPLIT (Az) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* determine the form, and check if inputs exist */ + /* ---------------------------------------------------------------------- */ + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + if (col_form) + { + vector = "column" ; /* column vectors */ + index = "row" ; /* with row indices */ + n = n_col ; + n_i = n_row ; + } + else + { + vector = "row" ; /* row vectors */ + index = "column" ; /* with column indices */ + n = n_row ; + n_i = n_col ; + } + + PRINTF (("%s-form matrix, n_row "ID" n_col "ID", ", vector, n_row, n_col)) ; + + if (n_row <= 0 || n_col <= 0) + { + PRINTF (("ERROR: n_row <= 0 or n_col <= 0\n\n")) ; + return (UMFPACK_ERROR_n_nonpositive) ; + } + + if (!Ap) + { + PRINTF (("ERROR: Ap missing\n\n")) ; + return (UMFPACK_ERROR_argument_missing) ; + } + + nz = Ap [n] ; + PRINTF (("nz = "ID". ", nz)) ; + if (nz < 0) + { + PRINTF (("ERROR: number of entries < 0\n\n")) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + + if (Ap [0] != 0) + { + PRINTF (("ERROR: Ap ["ID"] = "ID" must be "ID"\n\n", + (Int) INDEX (0), INDEX (Ap [0]), (Int) INDEX (0))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + + if (!Ai) + { + PRINTF (("ERROR: Ai missing\n\n")) ; + return (UMFPACK_ERROR_argument_missing) ; + } + + do_values = Ax != (double *) NULL ; + + PRINTF4 (("\n")) ; + + /* ---------------------------------------------------------------------- */ + /* check the row/column pointers, Ap */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n ; k++) + { + if (Ap [k] < 0) + { + PRINTF (("ERROR: Ap ["ID"] < 0\n\n", INDEX (k))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + if (Ap [k] > nz) + { + PRINTF (("ERROR: Ap ["ID"] > size of Ai\n\n", INDEX (k))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + } + + for (k = 0 ; k < n ; k++) + { + length = Ap [k+1] - Ap [k] ; + if (length < 0) + { + PRINTF (("ERROR: # entries in %s "ID" is < 0\n\n", + vector, INDEX (k))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* print each vector */ + /* ---------------------------------------------------------------------- */ + + prl1 = prl ; + + for (k = 0 ; k < n ; k++) + { + /* if prl is 4, print the first 10 entries of the first 10 vectors */ + if (k < 10) + { + prl = prl1 ; + } + /* get the vector pointers */ + p1 = Ap [k] ; + p2 = Ap [k+1] ; + length = p2 - p1 ; + PRINTF4 (("\n %s "ID": start: "ID" end: "ID" entries: "ID"\n", + vector, INDEX (k), p1, p2-1, length)) ; + ilast = EMPTY ; + for (p = p1 ; p < p2 ; p++) + { + i = Ai [p] ; + PRINTF4 (("\t%s "ID" ", index, INDEX (i))) ; + if (do_values && prl >= 4) + { + PRINTF ((":")) ; + ASSIGN (a, Ax, Az, p, split) ; + PRINT_ENTRY (a) ; + } + if (i < 0 || i >= n_i) + { + PRINTF ((" ERROR: %s index "ID" out of range in %s "ID"\n\n", + index, INDEX (i), vector, INDEX (k))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + if (i <= ilast) + { + PRINTF ((" ERROR: %s index "ID" out of order (or duplicate) in " + "%s "ID"\n\n", index, INDEX (i), vector, INDEX (k))) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + PRINTF4 (("\n")) ; + /* truncate printout, but continue to check matrix */ + if (prl == 4 && (p - p1) == 9 && length > 10) + { + PRINTF4 (("\t...\n")) ; + prl-- ; + } + ilast = i ; + } + /* truncate printout, but continue to check matrix */ + if (prl == 4 && k == 9 && n > 10) + { + PRINTF4 (("\n ...\n")) ; + prl-- ; + } + } + prl = prl1 ; + + /* ---------------------------------------------------------------------- */ + /* return the status of the matrix */ + /* ---------------------------------------------------------------------- */ + + PRINTF4 ((" %s-form matrix ", vector)) ; + PRINTF (("OK\n\n")) ; + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_numeric.c @@ -0,0 +1,663 @@ +/* ========================================================================== */ +/* === UMFPACK_report_numeric =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints the Numeric object. + See umfpack_report_numeric.h for details. + + Dynamic memory usage: Allocates a size n*sizeof(Int) workspace via a single + call to UMF_malloc and then frees all of it via UMF_free on return. The + workspace is not allocated if an early error return occurs before the + workspace is needed. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" +#include "umf_report_perm.h" +#include "umf_report_vector.h" +#include "umf_malloc.h" +#include "umf_free.h" + + +PRIVATE Int report_L +( + NumericType *Numeric, + Int Pattern [ ], + Int prl +) ; + + +PRIVATE Int report_U +( + NumericType *Numeric, + Int Pattern [ ], + Int prl +) ; + +/* ========================================================================== */ +/* === UMFPACK_report_numeric =============================================== */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_report_numeric +( + void *NumericHandle, + const double Control [UMFPACK_CONTROL] +) +{ + Int prl, *W, nn, n_row, n_col, n_inner, num_fixed_size, numeric_size, + npiv ; + NumericType *Numeric ; + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + PRINTF (("Numeric object: ")) ; + + Numeric = (NumericType *) NumericHandle ; + if (!UMF_valid_numeric (Numeric)) + { + PRINTF (("ERROR: LU factors invalid\n\n")) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + n_row = Numeric->n_row ; + n_col = Numeric->n_col ; + nn = MAX (n_row, n_col) ; + n_inner = MIN (n_row, n_col) ; + npiv = Numeric->npiv ; + + DEBUG1 (("n_row "ID" n_col "ID" nn "ID" n_inner "ID" npiv "ID"\n", + n_row, n_col, nn, n_inner, npiv)) ; + + /* size of Numeric object, except Numeric->Memory and Numeric->Upattern */ + /* see also UMF_set_stats */ + num_fixed_size = + UNITS (NumericType, 1) /* Numeric structure */ + + UNITS (Entry, n_inner+1) /* D */ + + UNITS (Int, n_row+1) /* Rperm */ + + UNITS (Int, n_col+1) /* Cperm */ + + 6 * UNITS (Int, npiv+1) /* Lpos, Uilen, Uip, Upos, Lilen, Lip */ + + ((Numeric->scale != UMFPACK_SCALE_NONE) ? + UNITS (Entry, n_row) : 0) ; /* Rs */ + + DEBUG1 (("num fixed size: "ID"\n", num_fixed_size)) ; + DEBUG1 (("Numeric->size "ID"\n", Numeric->size)) ; + DEBUG1 (("ulen units "ID"\n", UNITS (Int, Numeric->ulen))) ; + + /* size of Numeric->Memory is Numeric->size */ + /* size of Numeric->Upattern is Numeric->ulen */ + numeric_size = num_fixed_size + Numeric->size + + UNITS (Int, Numeric->ulen) ; + + DEBUG1 (("numeric total size "ID"\n", numeric_size)) ; + + if (prl >= 4) + { + PRINTF (("\n n_row: "ID" n_col: "ID"\n", n_row, n_col)) ; + + PRINTF ((" relative pivot tolerance used: %g\n", + Numeric->relpt)) ; + PRINTF ((" relative symmetric pivot tolerance used: %g\n", + Numeric->relpt2)) ; + + PRINTF ((" matrix scaled: ")) ; + if (Numeric->scale == UMFPACK_SCALE_NONE) + { + PRINTF (("no")) ; + } + else if (Numeric->scale == UMFPACK_SCALE_SUM) + { + PRINTF (("yes (divided each row by sum abs value in each row)\n")) ; + PRINTF ((" minimum sum (abs (rows of A)): %.5e\n", + Numeric->rsmin)) ; + PRINTF ((" maximum sum (abs (rows of A)): %.5e", + Numeric->rsmax)) ; + } + else if (Numeric->scale == UMFPACK_SCALE_MAX) + { + PRINTF (("yes (divided each row by max abs value in each row)\n")) ; + PRINTF ((" minimum max (abs (rows of A)): %.5e\n", + Numeric->rsmin)) ; + PRINTF ((" maximum max (abs (rows of A)): %.5e", + Numeric->rsmax)) ; + } + PRINTF (("\n")) ; + + PRINTF ((" initial allocation parameter used: %g\n", + Numeric->alloc_init)) ; + PRINTF ((" frontal matrix allocation parameter used: %g\n", + Numeric->front_alloc_init)) ; + PRINTF ((" final total size of Numeric object (Units): "ID"\n", + numeric_size)) ; + PRINTF ((" final total size of Numeric object (MBytes): %.1f\n", + MBYTES (numeric_size))) ; + PRINTF ((" peak size of variable-size part (Units): "ID"\n", + Numeric->max_usage)) ; + PRINTF ((" peak size of variable-size part (MBytes): %.1f\n", + MBYTES (Numeric->max_usage))) ; + PRINTF ((" largest actual frontal matrix size: "ID"\n", + Numeric->maxfrsize)) ; + PRINTF ((" memory defragmentations: "ID"\n", + Numeric->ngarbage)) ; + PRINTF ((" memory reallocations: "ID"\n", + Numeric->nrealloc)) ; + PRINTF ((" costly memory reallocations: "ID"\n", + Numeric->ncostly)) ; + PRINTF ((" entries in compressed pattern (L and U): "ID"\n", + Numeric->isize)) ; + PRINTF ((" number of nonzeros in L (excl diag): "ID"\n", + Numeric->lnz)) ; + PRINTF ((" number of entries stored in L (excl diag): "ID"\n", + Numeric->nLentries)) ; + PRINTF ((" number of nonzeros in U (excl diag): "ID"\n", + Numeric->unz)) ; + PRINTF ((" number of entries stored in U (excl diag): "ID"\n", + Numeric->nUentries)) ; + PRINTF ((" factorization floating-point operations: %g\n", + Numeric->flops)) ; + PRINTF ((" number of nonzeros on diagonal of U: "ID"\n", + Numeric->nnzpiv)) ; + PRINTF ((" min abs. value on diagonal of U: %.5e\n", + Numeric->min_udiag)) ; + PRINTF ((" max abs. value on diagonal of U: %.5e\n", + Numeric->max_udiag)) ; + PRINTF ((" reciprocal condition number estimate: %.2e\n", + Numeric->rcond)) ; + } + + W = (Int *) UMF_malloc (nn, sizeof (Int)) ; + if (!W) + { + PRINTF ((" ERROR: out of memory to check Numeric object\n\n")) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + if (Numeric->Rs) + { +#ifndef NRECIPROCAL + if (Numeric->do_recip) + { + PRINTF4 (("\nScale factors applied via multiplication\n")) ; + } + else +#endif + { + PRINTF4 (("\nScale factors applied via division\n")) ; + } + PRINTF4 (("Scale factors, Rs: ")) ; + (void) UMF_report_vector (n_row, Numeric->Rs, (double *) NULL, + prl, FALSE, TRUE) ; + } + else + { + PRINTF4 (("Scale factors, Rs: (not present)\n")) ; + } + + PRINTF4 (("\nP: row ")) ; + if (UMF_report_perm (n_row, Numeric->Rperm, W, prl, 0) != UMFPACK_OK) + { + (void) UMF_free ((void *) W) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + PRINTF4 (("\nQ: column ")) ; + if (UMF_report_perm (n_col, Numeric->Cperm, W, prl, 0) != UMFPACK_OK) + { + (void) UMF_free ((void *) W) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + if (!report_L (Numeric, W, prl)) + { + (void) UMF_free ((void *) W) ; + PRINTF ((" ERROR: L factor invalid\n\n")) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + if (!report_U (Numeric, W, prl)) + { + (void) UMF_free ((void *) W) ; + PRINTF ((" ERROR: U factor invalid\n\n")) ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + /* The diagonal of U is in "merged" (Entry) form, not "split" form. */ + PRINTF4 (("\ndiagonal of U: ")) ; + (void) UMF_report_vector (n_inner, (double *) Numeric->D, (double *) NULL, + prl, FALSE, FALSE) ; + + (void) UMF_free ((void *) W) ; + + PRINTF4 ((" Numeric object: ")) ; + PRINTF (("OK\n\n")) ; + return (UMFPACK_OK) ; +} + + +/* ========================================================================== */ +/* === report_L ============================================================= */ +/* ========================================================================== */ + +PRIVATE Int report_L +( + NumericType *Numeric, + Int Pattern [ ], + Int prl +) +{ + Int k, deg, *ip, j, row, n_row, *Lpos, *Lilen, valid, k1, + *Lip, newLchain, llen, prl1, pos, lp, p, npiv, n1, *Li ; + Entry *xp, *Lval ; + + /* ---------------------------------------------------------------------- */ + + ASSERT (prl >= 3) ; + + n_row = Numeric->n_row ; + npiv = Numeric->npiv ; + n1 = Numeric->n1 ; + Lpos = Numeric->Lpos ; + Lilen = Numeric->Lilen ; + Lip = Numeric->Lip ; + prl1 = prl ; + deg = 0 ; + + PRINTF4 (( + "\nL in Numeric object, in column-oriented compressed-pattern form:\n" + " Diagonal entries are all equal to 1.0 (not stored)\n")) ; + + ASSERT (Pattern != (Int *) NULL) ; + + /* ---------------------------------------------------------------------- */ + /* print L */ + /* ---------------------------------------------------------------------- */ + + k1 = 12 ; + + /* ---------------------------------------------------------------------- */ + /* print the singleton columns of L */ + /* ---------------------------------------------------------------------- */ + + for (k = 0 ; k < n1 ; k++) + { + if (k1 > 0) + { + prl = prl1 ; + } + lp = Lip [k] ; + deg = Lilen [k] ; + Li = (Int *) (Numeric->Memory + lp) ; + lp += UNITS (Int, deg) ; + Lval = (Entry *) (Numeric->Memory + lp) ; + if (k1-- > 0) + { + prl = prl1 ; + } + else if (prl == 4) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + PRINTF4 (("\n column "ID":", INDEX (k))) ; + PRINTF4 ((" length "ID".\n", deg)) ; + for (j = 0 ; j < deg ; j++) + { + row = Li [j] ; + PRINTF4 (("\trow "ID" : ", INDEX (row))) ; + if (prl >= 4) PRINT_ENTRY (Lval [j]) ; + if (row <= k || row >= n_row) + { + return (FALSE) ; + } + PRINTF4 (("\n")) ; + /* truncate printout, but continue to check L */ + if (prl == 4 && j == 9 && deg > 10) + { + PRINTF (("\t...\n")) ; + prl-- ; + } + } + } + + /* ---------------------------------------------------------------------- */ + /* print the regular columns of L */ + /* ---------------------------------------------------------------------- */ + + for (k = n1 ; k < npiv ; k++) + { + /* if prl is 4, print the first 10 entries of the first 10 columns */ + if (k1 > 0) + { + prl = prl1 ; + } + + lp = Lip [k] ; + newLchain = (lp < 0) ; + if (newLchain) + { + lp = -lp ; + deg = 0 ; + } + + if (k1-- > 0) + { + prl = prl1 ; + } + else if (prl == 4) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + + PRINTF4 (("\n column "ID":", INDEX (k))) ; + + /* ------------------------------------------------------------------ */ + /* make column of L in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + /* remove pivot row */ + pos = Lpos [k] ; + if (pos != EMPTY) + { + PRINTF4 ((" remove row "ID" at position "ID".", + INDEX (Pattern [pos]), INDEX (pos))) ; + valid = (!newLchain) && (deg > 0) && (pos < deg) && (pos >= 0) + && (Pattern [pos] == k) ; + if (!valid) + { + return (FALSE) ; + } + Pattern [pos] = Pattern [--deg] ; + } + + /* concatenate the pattern */ + llen = Lilen [k] ; + if (llen < 0) + { + return (FALSE) ; + } + p = lp + UNITS (Int, llen) ; + xp = (Entry *) (Numeric->Memory + p) ; + if ((llen > 0 || deg > 0) + && (p + (Int) UNITS (Entry, deg) > Numeric->size)) + { + return (FALSE) ; + } + if (llen > 0) + { + PRINTF4 ((" add "ID" entries.", llen)) ; + ip = (Int *) (Numeric->Memory + lp) ; + for (j = 0 ; j < llen ; j++) + { + Pattern [deg++] = *ip++ ; + } + } + + /* ------------------------------------------------------------------ */ + /* print column k of L */ + /* ------------------------------------------------------------------ */ + + PRINTF4 ((" length "ID".", deg)) ; + if (newLchain) + { + PRINTF4 ((" Start of Lchain.")) ; + } + PRINTF4 (("\n")) ; + + for (j = 0 ; j < deg ; j++) + { + row = Pattern [j] ; + PRINTF4 (("\trow "ID" : ", INDEX (row))) ; + if (prl >= 4) PRINT_ENTRY (*xp) ; + if (row <= k || row >= n_row) + { + return (FALSE) ; + } + PRINTF4 (("\n")) ; + xp++ ; + /* truncate printout, but continue to check L */ + if (prl == 4 && j == 9 && deg > 10) + { + PRINTF (("\t...\n")) ; + prl-- ; + } + } + } + + PRINTF4 (("\n")) ; + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === report_U ============================================================= */ +/* ========================================================================== */ + +PRIVATE Int report_U +( + NumericType *Numeric, + Int Pattern [ ], + Int prl +) +{ + /* ---------------------------------------------------------------------- */ + + Int k, deg, j, *ip, col, *Upos, *Uilen, k1, prl1, pos, + *Uip, n_col, ulen, p, newUchain, up, npiv, n1, *Ui ; + Entry *xp, *Uval ; + + /* ---------------------------------------------------------------------- */ + + ASSERT (prl >= 3) ; + + n_col = Numeric->n_col ; + npiv = Numeric->npiv ; + n1 = Numeric->n1 ; + Upos = Numeric->Upos ; + Uilen = Numeric->Uilen ; + Uip = Numeric->Uip ; + prl1 = prl ; + + PRINTF4 (( + "\nU in Numeric object, in row-oriented compressed-pattern form:\n" + " Diagonal is stored separately.\n")) ; + + ASSERT (Pattern != (Int *) NULL) ; + + k1 = 12 ; + + /* ---------------------------------------------------------------------- */ + /* print the sparse part of U */ + /* ---------------------------------------------------------------------- */ + + deg = Numeric->ulen ; + if (deg > 0) + { + /* make last pivot row of U (singular matrices only) */ + for (j = 0 ; j < deg ; j++) + { + Pattern [j] = Numeric->Upattern [j] ; + } + } + + PRINTF4 (("\n row "ID": length "ID". End of Uchain.\n", INDEX (npiv-1), + deg)) ; + + for (k = npiv-1 ; k >= n1 ; k--) + { + + /* ------------------------------------------------------------------ */ + /* print row k of U */ + /* ------------------------------------------------------------------ */ + + /* if prl is 3, print the first 10 entries of the first 10 columns */ + if (k1 > 0) + { + prl = prl1 ; + } + + up = Uip [k] ; + ulen = Uilen [k] ; + if (ulen < 0) + { + return (FALSE) ; + } + newUchain = (up < 0) ; + if (newUchain) + { + up = -up ; + p = up + UNITS (Int, ulen) ; + } + else + { + p = up ; + } + xp = (Entry *) (Numeric->Memory + p) ; + if (deg > 0 && (p + (Int) UNITS (Entry, deg) > Numeric->size)) + { + return (FALSE) ; + } + for (j = 0 ; j < deg ; j++) + { + col = Pattern [j] ; + PRINTF4 (("\tcol "ID" :", INDEX (col))) ; + if (prl >= 4) PRINT_ENTRY (*xp) ; + if (col <= k || col >= n_col) + { + return (FALSE) ; + } + PRINTF4 (("\n")) ; + xp++ ; + /* truncate printout, but continue to check U */ + if (prl == 4 && j == 9 && deg > 10) + { + PRINTF (("\t...\n")) ; + prl-- ; + } + } + + /* ------------------------------------------------------------------ */ + /* make row k-1 of U in Pattern [0..deg-1] */ + /* ------------------------------------------------------------------ */ + + if (k1-- > 0) + { + prl = prl1 ; + } + else if (prl == 4) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + + if (k > 0) + { + PRINTF4 (("\n row "ID": ", INDEX (k-1))) ; + } + + if (newUchain) + { + /* next row is a new Uchain */ + if (k > 0) + { + deg = ulen ; + PRINTF4 (("length "ID". End of Uchain.\n", deg)) ; + if (up + (Int) UNITS (Int, ulen) > Numeric->size) + { + return (FALSE) ; + } + ip = (Int *) (Numeric->Memory + up) ; + for (j = 0 ; j < deg ; j++) + { + Pattern [j] = *ip++ ; + } + } + } + else + { + if (ulen > 0) + { + PRINTF4 (("remove "ID" entries. ", ulen)) ; + } + deg -= ulen ; + if (deg < 0) + { + return (FALSE) ; + } + pos = Upos [k] ; + if (pos != EMPTY) + { + /* add the pivot column */ + PRINTF4 (("add column "ID" at position "ID". ", + INDEX (k), INDEX (pos))) ; + if (pos < 0 || pos > deg) + { + return (FALSE) ; + } + Pattern [deg++] = Pattern [pos] ; + Pattern [pos] = k ; + } + PRINTF4 (("length "ID".\n", deg)) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* print the singleton rows of U */ + /* ---------------------------------------------------------------------- */ + + for (k = n1 - 1 ; k >= 0 ; k--) + { + if (k1 > 0) + { + prl = prl1 ; + } + up = Uip [k] ; + deg = Uilen [k] ; + Ui = (Int *) (Numeric->Memory + up) ; + up += UNITS (Int, deg) ; + Uval = (Entry *) (Numeric->Memory + up) ; + if (k1-- > 0) + { + prl = prl1 ; + } + else if (prl == 4) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + PRINTF4 (("\n row "ID":", INDEX (k))) ; + PRINTF4 ((" length "ID".\n", deg)) ; + for (j = 0 ; j < deg ; j++) + { + col = Ui [j] ; + PRINTF4 (("\tcol "ID" : ", INDEX (col))) ; + if (prl >= 4) PRINT_ENTRY (Uval [j]) ; + if (col <= k || col >= n_col) + { + return (FALSE) ; + } + PRINTF4 (("\n")) ; + /* truncate printout, but continue to check U */ + if (prl == 4 && j == 9 && deg > 10) + { + PRINTF (("\t...\n")) ; + prl-- ; + } + } + } + + prl = prl1 ; + PRINTF4 (("\n")) ; + return (TRUE) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_perm.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_perm.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_perm.c @@ -0,0 +1,44 @@ +/* ========================================================================== */ +/* === UMFPACK_report_perm ================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints a permutation vector. See umfpack_report_perm.h + for details. + + Dynamic memory usage: Allocates a size max(np,1)*sizeof(Int) workspace via + a single call to UMF_malloc and then frees all of it via UMF_free on return. +*/ + +#include "umf_internal.h" +#include "umf_report_perm.h" +#include "umf_malloc.h" +#include "umf_free.h" + +GLOBAL Int UMFPACK_report_perm +( + Int np, + const Int Perm [ ], + const double Control [UMFPACK_CONTROL] +) +{ + Int prl, *W, status ; + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + W = (Int *) UMF_malloc (MAX (np,1), sizeof (Int)) ; + status = UMF_report_perm (np, Perm, W, prl, 1) ; + (void) UMF_free ((void *) W) ; + return (status) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_status.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_status.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_status.c @@ -0,0 +1,118 @@ +/* ========================================================================== */ +/* === UMFPACK_report_status ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints the return value from other UMFPACK_* routines. + See umfpack_report_status.h for details. +*/ + +#include "umf_internal.h" + +GLOBAL void UMFPACK_report_status +( + const double Control [UMFPACK_CONTROL], + Int status +) +{ + Int prl ; + + /* ---------------------------------------------------------------------- */ + /* get control settings and status to determine what to print */ + /* ---------------------------------------------------------------------- */ + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl < 1) + { + /* no output generated if prl is less than 1 */ + return ; + } + + if (status == UMFPACK_OK && prl <= 1) + { + /* no output generated if prl is 1 or less and no error occurred. */ + /* note that the default printing level is 1. */ + return ; + } + + /* ---------------------------------------------------------------------- */ + /* print umfpack license, copyright, version, and status condition */ + /* ---------------------------------------------------------------------- */ + + PRINTF (("\n")) ; + PRINTF4 (("%s\n", UMFPACK_COPYRIGHT)) ; + PRINTF6 (("%s", UMFPACK_LICENSE_PART1)) ; + PRINTF6 (("%s", UMFPACK_LICENSE_PART2)) ; + PRINTF6 (("%s", UMFPACK_LICENSE_PART3)) ; + PRINTF (("%s: ", UMFPACK_VERSION)) ; + + switch (status) + { + case UMFPACK_OK: + PRINTF (("OK\n")) ; + break ; + + case UMFPACK_WARNING_singular_matrix: + PRINTF (("WARNING: matrix is singular\n")) ; + break ; + + case UMFPACK_ERROR_out_of_memory: + PRINTF (("ERROR: out of memory\n")) ; + break ; + + case UMFPACK_ERROR_invalid_Numeric_object: + PRINTF (("ERROR: Numeric object is invalid\n")) ; + break ; + + case UMFPACK_ERROR_invalid_Symbolic_object: + PRINTF (("ERROR: Symbolic object is invalid\n")) ; + break ; + + case UMFPACK_ERROR_argument_missing: + PRINTF (("ERROR: required argument(s) missing\n")) ; + break ; + + case UMFPACK_ERROR_n_nonpositive: + PRINTF (("ERROR: dimension (n_row or n_col) must be > 0\n")) ; + break ; + + case UMFPACK_ERROR_invalid_matrix: + PRINTF (("ERROR: input matrix is invalid\n")) ; + break ; + + case UMFPACK_ERROR_invalid_system: + PRINTF (("ERROR: system argument invalid\n")) ; + break ; + + case UMFPACK_ERROR_invalid_permutation: + PRINTF (("ERROR: invalid permutation\n")) ; + break ; + + case UMFPACK_ERROR_different_pattern: + PRINTF (("ERROR: pattern of matrix (Ap and/or Ai) has changed\n")) ; + break ; + + case UMFPACK_ERROR_internal_error: + PRINTF (("INTERNAL ERROR!\n" + "Input arguments might be corrupted or aliased, or an internal\n" + "error has occurred. Check your input arguments with the\n" + "umfpack_*_report_* routines before calling the umfpack_*\n" + "computational routines. Recompile UMFPACK with debugging\n" + "enabled, and look for failed assertions. If all else fails\n" + "please report this error to Tim Davis (davis@cise.ufl.edu).\n" + )) ; + break ; + + default: + PRINTF (("ERROR: Unrecognized error code: "ID"\n", status)) ; + + } + PRINTF (("\n")) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_symbolic.c @@ -0,0 +1,228 @@ +/* ========================================================================== */ +/* === UMFPACK_report_symbolic ============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints the Symbolic object. See umfpack_report_symbolic.h + for details. Does not print new Cdeg, Rdeg, Esize, and the Diagonal_map. + + Dynamic memory usage: Allocates a size MAX (n_row,n_col)*sizeof(Int) + workspace via a single call to UMF_malloc and then frees all of it via + UMF_free on return. The workspace is not allocated if an early error + return occurs before the workspace is needed. +*/ + +#include "umf_internal.h" +#include "umf_valid_symbolic.h" +#include "umf_report_perm.h" +#include "umf_malloc.h" +#include "umf_free.h" + +GLOBAL Int UMFPACK_report_symbolic +( + void *SymbolicHandle, + const double Control [UMFPACK_CONTROL] +) +{ + Int n_row, n_col, nz, nchains, nfr, maxnrows, maxncols, prl, + k, chain, frontid, frontid1, frontid2, kk, *Chain_start, *W, + *Chain_maxrows, *Chain_maxcols, *Front_npivcol, *Front_1strow, + *Front_leftmostdesc, *Front_parent, done, status1, status2 ; + SymbolicType *Symbolic ; + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + PRINTF (("Symbolic object: ")) ; + + Symbolic = (SymbolicType *) SymbolicHandle ; + if (!UMF_valid_symbolic (Symbolic)) + { + PRINTF (("ERROR: invalid\n")) ; + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + n_row = Symbolic->n_row ; + n_col = Symbolic->n_col ; + + nz = Symbolic->nz ; + + nchains = Symbolic->nchains ; + nfr = Symbolic->nfr ; + maxnrows = Symbolic->maxnrows ; + maxncols = Symbolic->maxncols ; + + Chain_start = Symbolic->Chain_start ; + Chain_maxrows = Symbolic->Chain_maxrows ; + Chain_maxcols = Symbolic->Chain_maxcols ; + Front_npivcol = Symbolic->Front_npivcol ; + Front_1strow = Symbolic->Front_1strow ; + Front_leftmostdesc = Symbolic->Front_leftmostdesc ; + Front_parent = Symbolic->Front_parent ; + + if (prl >= 4) + { + + PRINTF (("\n matrix to be factorized:\n")) ; + PRINTF (("\tn_row: "ID" n_col: "ID"\n", n_row, n_col)) ; + PRINTF (("\tnumber of entries: "ID"\n", nz)) ; + PRINTF ((" block size used for dense matrix kernels: "ID"\n", + Symbolic->nb)) ; + + PRINTF ((" strategy used: ")) ; + /* strategy cannot be auto */ + if (Symbolic->strategy == UMFPACK_STRATEGY_SYMMETRIC) + { + PRINTF (("symmetric")) ; + } + else if (Symbolic->strategy == UMFPACK_STRATEGY_UNSYMMETRIC) + { + PRINTF (("unsymmetric")) ; + } + else if (Symbolic->strategy == UMFPACK_STRATEGY_2BY2) + { + PRINTF (("symmetric 2-by-2")) ; + } + PRINTF (("\n")) ; + + PRINTF ((" ordering used: ")) ; + if (Symbolic->ordering == UMFPACK_ORDERING_COLAMD) + { + PRINTF (("colamd on A\n")) ; + } + else if (Symbolic->ordering == UMFPACK_ORDERING_AMD) + { + PRINTF (("amd on A+A'\n")) ; + } + else if (Symbolic->ordering == UMFPACK_ORDERING_GIVEN) + { + PRINTF (("provided by user")) ; + } + PRINTF (("\n")) ; + + PRINTF ((" performn column etree postorder: ")) ; + if (Symbolic->fixQ) + { + PRINTF (("no\n")) ; + } + else + { + PRINTF (("yes\n")) ; + } + + PRINTF ((" prefer diagonal pivoting (attempt P=Q): ")) ; + if (Symbolic->prefer_diagonal) + { + PRINTF (("yes\n")) ; + } + else + { + PRINTF (("no\n")) ; + } + + PRINTF ((" variable-size part of Numeric object:\n")) ; + PRINTF (("\tminimum initial size (Units): %.20g (MBytes): %.1f\n", + Symbolic->dnum_mem_init_usage, + MBYTES (Symbolic->dnum_mem_init_usage))) ; + PRINTF (("\testimated peak size (Units): %.20g (MBytes): %.1f\n", + Symbolic->num_mem_usage_est, + MBYTES (Symbolic->num_mem_usage_est))) ; + PRINTF (("\testimated final size (Units): %.20g (MBytes): %.1f\n", + Symbolic->num_mem_size_est, + MBYTES (Symbolic->num_mem_size_est))) ; + PRINTF ((" symbolic factorization memory usage (Units):" + " %.20g (MBytes): %.1f\n", + Symbolic->peak_sym_usage, + MBYTES (Symbolic->peak_sym_usage))) ; + PRINTF ((" frontal matrices / supercolumns:\n")) ; + PRINTF (("\tnumber of frontal chains: "ID"\n", nchains)) ; + PRINTF (("\tnumber of frontal matrices: "ID"\n", nfr)) ; + PRINTF (("\tlargest frontal matrix row dimension: "ID"\n", maxnrows)) ; + PRINTF (("\tlargest frontal matrix column dimension: "ID"\n",maxncols)); + } + + k = 0 ; + done = FALSE ; + + for (chain = 0 ; chain < nchains ; chain++) + { + frontid1 = Chain_start [chain] ; + frontid2 = Chain_start [chain+1] - 1 ; + PRINTF4 (("\n Frontal chain: "ID". Frontal matrices "ID" to "ID"\n", + INDEX (chain), INDEX (frontid1), INDEX (frontid2))) ; + PRINTF4 (("\tLargest frontal matrix in Frontal chain: "ID"-by-"ID"\n", + Chain_maxrows [chain], Chain_maxcols [chain])) ; + for (frontid = frontid1 ; frontid <= frontid2 ; frontid++) + { + kk = Front_npivcol [frontid] ; + PRINTF4 (("\tFront: "ID" pivot cols: "ID" (pivot columns "ID" to " + ID")\n", INDEX (frontid), kk, INDEX (k), INDEX (k+kk-1))) ; + PRINTF4 (("\t pivot row candidates: "ID" to "ID"\n", + INDEX (Front_1strow [Front_leftmostdesc [frontid]]), + INDEX (Front_1strow [frontid+1]-1))) ; + PRINTF4 (("\t leftmost descendant: "ID"\n", + INDEX (Front_leftmostdesc [frontid]))) ; + PRINTF4 (("\t 1st new candidate row : "ID"\n", + INDEX (Front_1strow [frontid]))) ; + PRINTF4 (("\t parent:")) ; + if (Front_parent [frontid] == EMPTY) + { + PRINTF4 ((" (none)\n")) ; + } + else + { + PRINTF4 ((" "ID"\n", INDEX (Front_parent [frontid]))) ; + } + done = (frontid == 20 && frontid < nfr-1 && prl == 4) ; + if (done) + { + PRINTF4 (("\t...\n")) ; + break ; + } + k += kk ; + } + if (Front_npivcol [nfr] != 0) + { + PRINTF4 (("\tFront: "ID" placeholder for "ID" empty columns\n", + INDEX (nfr), Front_npivcol [nfr])) ; + } + if (done) + { + break ; + } + } + + W = (Int *) UMF_malloc (MAX (n_row, n_col), sizeof (Int)) ; + if (!W) + { + PRINTF (("ERROR: out of memory to check Symbolic object\n\n")) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + PRINTF4 (("\nInitial column permutation, Q1: ")) ; + status1 = UMF_report_perm (n_col, Symbolic->Cperm_init, W, prl, 0) ; + + PRINTF4 (("\nInitial row permutation, P1: ")) ; + status2 = UMF_report_perm (n_row, Symbolic->Rperm_init, W, prl, 0) ; + + (void) UMF_free ((void *) W) ; + + if (status1 != UMFPACK_OK || status2 != UMFPACK_OK) + { + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + PRINTF4 ((" Symbolic object: ")) ; + PRINTF (("OK\n\n")) ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_triplet.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_triplet.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_triplet.c @@ -0,0 +1,99 @@ +/* ========================================================================== */ +/* === UMFPACK_report_triplet =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints a matrix in triplet form. See + umfpack_report_triplet.h for details. +*/ + +#include "umf_internal.h" + +GLOBAL Int UMFPACK_report_triplet +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], + const Int Tj [ ], + const double Tx [ ], +#ifdef COMPLEX + const double Tz [ ], +#endif + const double Control [UMFPACK_CONTROL] +) +{ + Entry t ; + Int prl, prl1, k, i, j, do_values ; +#ifdef COMPLEX + Int split = SPLIT (Tz) ; +#endif + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + PRINTF (("triplet-form matrix, n_row = "ID", n_col = "ID" nz = "ID". ", + n_row, n_col, nz)) ; + + if (!Ti || !Tj) + { + PRINTF (("ERROR: indices not present\n\n")) ; + return (UMFPACK_ERROR_argument_missing) ; + } + + if (n_row <= 0 || n_col <= 0) + { + PRINTF (("ERROR: n_row or n_col is <= 0\n\n")) ; + return (UMFPACK_ERROR_n_nonpositive) ; + } + + if (nz < 0) + { + PRINTF (("ERROR: nz is < 0\n\n")) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + + PRINTF4 (("\n")) ; + + do_values = Tx != (double *) NULL ; + + prl1 = prl ; + for (k = 0 ; k < nz ; k++) + { + i = Ti [k] ; + j = Tj [k] ; + PRINTF4 ((" "ID" : "ID" "ID" ", INDEX (k), INDEX (i), INDEX (j))) ; + if (do_values && prl >= 4) + { + ASSIGN (t, Tx, Tz, k, split) ; + PRINT_ENTRY (t) ; + } + PRINTF4 (("\n")) ; + if (i < 0 || i >= n_row || j < 0 || j >= n_col) + { + /* invalid triplet */ + PRINTF (("ERROR: invalid triplet\n\n")) ; + return (UMFPACK_ERROR_invalid_matrix) ; + } + if (prl == 4 && k == 9 && nz > 10) + { + PRINTF ((" ...\n")) ; + prl-- ; + } + } + prl = prl1 ; + + PRINTF4 ((" triplet-form matrix ")) ; + PRINTF (("OK\n\n")) ; + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_vector.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_vector.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_report_vector.c @@ -0,0 +1,43 @@ +/* ========================================================================== */ +/* === UMFPACK_report_vector ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Prints a real or complex vector. + See umfpack_report_vector.h for details. +*/ + +#include "umf_internal.h" +#include "umf_report_vector.h" + +GLOBAL Int UMFPACK_report_vector +( + Int n, + const double Xx [ ], +#ifdef COMPLEX + const double Xz [ ], +#endif + const double Control [UMFPACK_CONTROL] +) +{ + Int prl ; + +#ifndef COMPLEX + double *Xz = (double *) NULL ; +#endif + + prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ; + + if (prl <= 2) + { + return (UMFPACK_OK) ; + } + + return (UMF_report_vector (n, Xx, Xz, prl, TRUE, FALSE)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_numeric.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_numeric.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_numeric.c @@ -0,0 +1,92 @@ +/* ========================================================================== */ +/* === UMFPACK_save_numeric ================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Saves a Numeric object to a file. It can later be read back + in via a call to umfpack_*_load_numeric. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" + +#define WRITE(object,type,n) \ +{ \ + ASSERT (object != (type *) NULL) ; \ + if (fwrite (object, sizeof (type), n, f) != n) \ + { \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ +} + +/* ========================================================================== */ +/* === UMFPACK_save_numeric ================================================= */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_save_numeric +( + void *NumericHandle, + char *user_filename +) +{ + NumericType *Numeric ; + char *filename ; + FILE *f ; + + /* get the Numeric object */ + Numeric = (NumericType *) NumericHandle ; + + /* make sure the Numeric object is valid */ + if (!UMF_valid_numeric (Numeric)) + { + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + /* get the filename, or use the default name if filename is NULL */ + if (user_filename == (char *) NULL) + { + filename = "numeric.umf" ; + } + else + { + filename = user_filename ; + } + f = fopen (filename, "wb") ; + if (!f) + { + return (UMFPACK_ERROR_file_IO) ; + } + + /* write the Numeric object to the file, in binary */ + WRITE (Numeric, NumericType, 1) ; + WRITE (Numeric->D, Entry, MIN (Numeric->n_row, Numeric->n_col)+1) ; + WRITE (Numeric->Rperm, Int, Numeric->n_row+1) ; + WRITE (Numeric->Cperm, Int, Numeric->n_col+1) ; + WRITE (Numeric->Lpos, Int, Numeric->npiv+1) ; + WRITE (Numeric->Lilen, Int, Numeric->npiv+1) ; + WRITE (Numeric->Lip, Int, Numeric->npiv+1) ; + WRITE (Numeric->Upos, Int, Numeric->npiv+1) ; + WRITE (Numeric->Uilen, Int, Numeric->npiv+1) ; + WRITE (Numeric->Uip, Int, Numeric->npiv+1) ; + if (Numeric->scale != UMFPACK_SCALE_NONE) + { + WRITE (Numeric->Rs, double, Numeric->n_row) ; + } + if (Numeric->ulen > 0) + { + WRITE (Numeric->Upattern, Int, Numeric->ulen+1) ; + } + WRITE (Numeric->Memory, Unit, Numeric->size) ; + + /* close the file */ + fclose (f) ; + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_save_symbolic.c @@ -0,0 +1,95 @@ +/* ========================================================================== */ +/* === UMFPACK_save_symbolic ================================================ */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Saves a Symbolic object to a file. It can later be read + back in via a call to umfpack_*_load_symbolic. +*/ + +#include "umf_internal.h" +#include "umf_valid_symbolic.h" + +#define WRITE(object,type,n) \ +{ \ + ASSERT (object != (type *) NULL) ; \ + if (fwrite (object, sizeof (type), n, f) != n) \ + { \ + fclose (f) ; \ + return (UMFPACK_ERROR_file_IO) ; \ + } \ +} + +/* ========================================================================== */ +/* === UMFPACK_save_symbolic ================================================ */ +/* ========================================================================== */ + +GLOBAL Int UMFPACK_save_symbolic +( + void *SymbolicHandle, + char *user_filename +) +{ + SymbolicType *Symbolic ; + char *filename ; + FILE *f ; + + /* get the Symbolic object */ + Symbolic = (SymbolicType *) SymbolicHandle ; + + /* make sure the Symbolic object is valid */ + if (!UMF_valid_symbolic (Symbolic)) + { + return (UMFPACK_ERROR_invalid_Symbolic_object) ; + } + + /* get the filename, or use the default name if filename is NULL */ + if (user_filename == (char *) NULL) + { + filename = "symbolic.umf" ; + } + else + { + filename = user_filename ; + } + f = fopen (filename, "wb") ; + if (!f) + { + return (UMFPACK_ERROR_file_IO) ; + } + + /* write the Symbolic object to the file, in binary */ + WRITE (Symbolic, SymbolicType, 1) ; + WRITE (Symbolic->Cperm_init, Int, Symbolic->n_col+1) ; + WRITE (Symbolic->Rperm_init, Int, Symbolic->n_row+1) ; + WRITE (Symbolic->Front_npivcol, Int, Symbolic->nfr+1) ; + WRITE (Symbolic->Front_parent, Int, Symbolic->nfr+1) ; + WRITE (Symbolic->Front_1strow, Int, Symbolic->nfr+1) ; + WRITE (Symbolic->Front_leftmostdesc, Int, Symbolic->nfr+1) ; + WRITE (Symbolic->Chain_start, Int, Symbolic->nchains+1) ; + WRITE (Symbolic->Chain_maxrows, Int, Symbolic->nchains+1) ; + WRITE (Symbolic->Chain_maxcols, Int, Symbolic->nchains+1) ; + WRITE (Symbolic->Cdeg, Int, Symbolic->n_col+1) ; + WRITE (Symbolic->Rdeg, Int, Symbolic->n_row+1) ; + if (Symbolic->esize > 0) + { + /* only when dense rows are present */ + WRITE (Symbolic->Esize, Int, Symbolic->esize) ; + } + if (Symbolic->prefer_diagonal) + { + /* only when diagonal pivoting is prefered */ + WRITE (Symbolic->Diagonal_map, Int, Symbolic->n_col+1) ; + } + + /* close the file */ + fclose (f) ; + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_scale.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_scale.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_scale.c @@ -0,0 +1,158 @@ +/* ========================================================================== */ +/* === UMFPACK_scale ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Applies the scale factors computed during numerical + factorization to a vector. See umfpack_scale.h for more details. + + The LU factorization is L*U = P*R*A*Q, where P and Q are permutation + matrices, and R is diagonal. This routine computes X = R * B using the + matrix R stored in the Numeric object. + + Returns FALSE if any argument is invalid, TRUE otherwise. + + If R not present in the Numeric object, then R = I and no floating-point + work is done. B is simply copied into X. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" + +GLOBAL Int UMFPACK_scale +( + double Xx [ ], +#ifdef COMPLEX + double Xz [ ], +#endif + const double Bx [ ], +#ifdef COMPLEX + const double Bz [ ], +#endif + void *NumericHandle +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + NumericType *Numeric ; + Int n, i ; + double *Rs ; +#ifdef COMPLEX + Int split = SPLIT (Xz) && SPLIT (Bz) ; +#endif + + Numeric = (NumericType *) NumericHandle ; + if (!UMF_valid_numeric (Numeric)) + { + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + n = Numeric->n_row ; + Rs = Numeric->Rs ; + + if (!Xx || !Bx) + { + return (UMFPACK_ERROR_argument_missing) ; + } + + /* ---------------------------------------------------------------------- */ + /* X = R*B or R\B */ + /* ---------------------------------------------------------------------- */ + + if (Rs != (double *) NULL) + { +#ifndef NRECIPROCAL + if (Numeric->do_recip) + { + /* multiply by the scale factors */ +#ifdef COMPLEX + if (split) + { + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] * Rs [i] ; + Xz [i] = Bz [i] * Rs [i] ; + } + } + else + { + for (i = 0 ; i < n ; i++) + { + Xx [2*i ] = Bx [2*i ] * Rs [i] ; + Xx [2*i+1] = Bx [2*i+1] * Rs [i] ; + } + } +#else + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] * Rs [i] ; + } +#endif + } + else +#endif + { + /* divide by the scale factors */ +#ifdef COMPLEX + if (split) + { + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] / Rs [i] ; + Xz [i] = Bz [i] / Rs [i] ; + } + } + else + { + for (i = 0 ; i < n ; i++) + { + Xx [2*i ] = Bx [2*i ] / Rs [i] ; + Xx [2*i+1] = Bx [2*i+1] / Rs [i] ; + } + } +#else + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] / Rs [i] ; + } +#endif + } + } + else + { + /* no scale factors, just copy B into X */ +#ifdef COMPLEX + if (split) + { + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] ; + Xz [i] = Bz [i] ; + } + } + else + { + for (i = 0 ; i < n ; i++) + { + Xx [2*i ] = Bx [2*i ] ; + Xx [2*i+1] = Bx [2*i+1] ; + } + } +#else + for (i = 0 ; i < n ; i++) + { + Xx [i] = Bx [i] ; + } +#endif + } + + return (UMFPACK_OK) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_solve.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_solve.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_solve.c @@ -0,0 +1,245 @@ +/* ========================================================================== */ +/* === UMFPACK_solve ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Solves a linear system using the numerical factorization + computed by UMFPACK_numeric. See umfpack_solve.h for more details. + + For umfpack_*_solve: + Dynamic memory usage: UMFPACK_solve calls UMF_malloc twice, for + workspace of size c*n*sizeof(double) + n*sizeof(Int), where c is + defined below. On return, all of this workspace is free'd via UMF_free. + + For umfpack_*_wsolve: + No dynamic memory usage. Input arrays are used for workspace instead. + Pattern is a workspace of size n Integers. The double array W must be + at least of size c*n, where c is defined below. + + If iterative refinement is requested, and Ax=b, A'x=b or A.'x=b is being + solved, and the matrix A is not singular, then c is 5 for the real version + and 10 for the complex version. Otherwise, c is 1 for the real version and + 4 for the complex version. +*/ + +#include "umf_internal.h" +#include "umf_valid_numeric.h" +#include "umf_solve.h" + +#ifndef WSOLVE +#include "umf_malloc.h" +#include "umf_free.h" +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif +#endif + +GLOBAL Int +#ifdef WSOLVE +UMFPACK_wsolve +#else +UMFPACK_solve +#endif +( + Int sys, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + double Xx [ ], +#ifdef COMPLEX + double Xz [ ], +#endif + const double Bx [ ], +#ifdef COMPLEX + const double Bz [ ], +#endif + void *NumericHandle, + const double Control [UMFPACK_CONTROL], + double User_Info [UMFPACK_INFO] +#ifdef WSOLVE + , Int Pattern [ ], + double W [ ] +#endif +) +{ + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + double Info2 [UMFPACK_INFO], stats [2] ; + double *Info ; + NumericType *Numeric ; + Int n, i, irstep, status ; +#ifndef WSOLVE + Int *Pattern, wsize ; + double *W ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get the amount of time used by the process so far */ + /* ---------------------------------------------------------------------- */ + + umfpack_tic (stats) ; + +#ifndef WSOLVE +#ifndef NDEBUG + init_count = UMF_malloc_count ; +#endif +#endif + + /* ---------------------------------------------------------------------- */ + /* get parameters */ + /* ---------------------------------------------------------------------- */ + + irstep = GET_CONTROL (UMFPACK_IRSTEP, UMFPACK_DEFAULT_IRSTEP) ; + + if (User_Info != (double *) NULL) + { + /* return Info in user's array */ + Info = User_Info ; + /* clear the parts of Info that are set by UMFPACK_solve */ + for (i = UMFPACK_IR_TAKEN ; i <= UMFPACK_SOLVE_TIME ; i++) + { + Info [i] = EMPTY ; + } + } + else + { + /* no Info array passed - use local one instead */ + Info = Info2 ; + for (i = 0 ; i < UMFPACK_INFO ; i++) + { + Info [i] = EMPTY ; + } + } + + Info [UMFPACK_STATUS] = UMFPACK_OK ; + Info [UMFPACK_SOLVE_FLOPS] = 0 ; + + Numeric = (NumericType *) NumericHandle ; + if (!UMF_valid_numeric (Numeric)) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Numeric_object ; + return (UMFPACK_ERROR_invalid_Numeric_object) ; + } + + Info [UMFPACK_NROW] = Numeric->n_row ; + Info [UMFPACK_NCOL] = Numeric->n_col ; + + if (Numeric->n_row != Numeric->n_col) + { + /* only square systems can be handled */ + Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_system ; + return (UMFPACK_ERROR_invalid_system) ; + } + n = Numeric->n_row ; + if (Numeric->nnzpiv < n + || SCALAR_IS_ZERO (Numeric->rcond) || SCALAR_IS_NAN (Numeric->rcond)) + { + /* turn off iterative refinement if A is singular */ + /* or if U has NaN's on the diagonal. */ + irstep = 0 ; + } + + if (!Xx || !Bx) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; + return (UMFPACK_ERROR_argument_missing) ; + } + + if (sys >= UMFPACK_Pt_L) + { + /* no iterative refinement except for nonsingular Ax=b, A'x=b, A.'x=b */ + irstep = 0 ; + } + + /* ---------------------------------------------------------------------- */ + /* allocate or check the workspace */ + /* ---------------------------------------------------------------------- */ + +#ifdef WSOLVE + + if (!W || !Pattern) + { + Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; + return (UMFPACK_ERROR_argument_missing) ; + } + +#else + +#ifdef COMPLEX + if (irstep > 0) + { + wsize = 10*n ; /* W, X, Z, S, Y, B2 */ + } + else + { + wsize = 4*n ; /* W, X */ + } +#else + if (irstep > 0) + { + wsize = 5*n ; /* W, Z, S, Y, B2 */ + } + else + { + wsize = n ; /* W */ + } +#endif + + Pattern = (Int *) UMF_malloc (n, sizeof (Int)) ; + W = (double *) UMF_malloc (wsize, sizeof (double)) ; + if (!W || !Pattern) + { + DEBUGm4 (("out of memory: solve work\n")) ; + Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; + (void) UMF_free ((void *) W) ; + (void) UMF_free ((void *) Pattern) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + +#endif /* WSOLVE */ + + /* ---------------------------------------------------------------------- */ + /* solve the system */ + /* ---------------------------------------------------------------------- */ + + status = UMF_solve (sys, Ap, Ai, Ax, Xx, Bx, +#ifdef COMPLEX + Az, Xz, Bz, +#endif + Numeric, irstep, Info, Pattern, W) ; + + /* ---------------------------------------------------------------------- */ + /* free the workspace (if allocated) */ + /* ---------------------------------------------------------------------- */ + +#ifndef WSOLVE + (void) UMF_free ((void *) W) ; + (void) UMF_free ((void *) Pattern) ; + ASSERT (UMF_malloc_count == init_count) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* get the time used by UMFPACK_*solve */ + /* ---------------------------------------------------------------------- */ + + Info [UMFPACK_STATUS] = status ; + if (status >= 0) + { + umfpack_toc (stats) ; + Info [UMFPACK_SOLVE_WALLTIME] = stats [0] ; + Info [UMFPACK_SOLVE_TIME] = stats [1] ; + } + + return (status) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_symbolic.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_symbolic.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_symbolic.c @@ -0,0 +1,39 @@ +/* ========================================================================== */ +/* === UMFPACK_symbolic ===================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Performs a symbolic factorization. + See umfpack_symbolic.h for details. +*/ + +#include "umf_internal.h" + +GLOBAL Int UMFPACK_symbolic +( + Int n_row, + Int n_col, + const Int Ap [ ], + const Int Ai [ ], + const double Ax [ ], +#ifdef COMPLEX + const double Az [ ], +#endif + void **SymbolicHandle, + const double Control [UMFPACK_CONTROL], + double Info [UMFPACK_INFO] +) +{ + Int *Qinit = (Int *) NULL ; + return (UMFPACK_qsymbolic (n_row, n_col, Ap, Ai, Ax, +#ifdef COMPLEX + Az, +#endif + Qinit, SymbolicHandle, Control, Info)) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_tictoc.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_tictoc.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_tictoc.c @@ -0,0 +1,106 @@ +/* ========================================================================== */ +/* === umfpack_tictoc ======================================================= */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Returns the time in seconds used by the process, and + the current wall clock time. BE CAREFUL: if you compare the run time of + UMFPACK with other sparse matrix packages, be sure to use the same timer. + See umfpack_tictoc.h for details. + + These routines conform to the POSIX standard. See umf_config.h for + more details. +*/ + +#include "umf_internal.h" + +#ifdef NO_TIMER + +/* -------------------------------------------------------------------------- */ +/* no timer used if -DNO_TIMER is defined at compile time */ +/* -------------------------------------------------------------------------- */ + +void umfpack_tic (double stats [2]) +{ + stats [0] = 0 ; + stats [1] = 0 ; +} + +void umfpack_toc (double stats [2]) +{ + stats [0] = 0 ; + stats [1] = 0 ; +} + +#else + +/* -------------------------------------------------------------------------- */ +/* timer routines, using either times() or clock() */ +/* -------------------------------------------------------------------------- */ + +#define TINY_TIME 1e-4 + +#ifndef NPOSIX + +#include +#include + +void umfpack_tic (double stats [2]) +{ + /* Return the current time */ + /* stats [0]: current wallclock time, in seconds */ + /* stats [1]: user + system time for the process, in seconds */ + + double ticks ; + struct tms t ; + + ticks = (double) sysconf (_SC_CLK_TCK) ; + stats [0] = (double) times (&t) / ticks ; + stats [1] = (double) (t.tms_utime + t.tms_stime) / ticks ; + + /* if time is tiny, just return zero */ + if (stats [0] < TINY_TIME) stats [0] = 0 ; + if (stats [1] < TINY_TIME) stats [1] = 0 ; +} + +#else + +/* Generic ANSI C: use the ANSI clock function. No wallclock time. */ + +#include + +void umfpack_tic (double stats [2]) +{ + stats [0] = 0 ; + stats [1] = ((double) (clock ( ))) / ((double) (CLOCKS_PER_SEC)) ; + if (stats [1] < TINY_TIME) stats [1] = 0 ; +} + +#endif + +/* -------------------------------------------------------------------------- */ + +void umfpack_toc (double stats [2]) +{ + /* Return the current time since the last call to umfpack_tic. */ + /* On input, stats holds the values returned by umfpack_tic. */ + /* On ouput, stats holds the time since the last umfpack_tic. */ + + double done [2] ; + umfpack_tic (done) ; + + stats [0] = done [0] - stats [0] ; + stats [1] = done [1] - stats [1] ; + + if (stats [0] < 0) stats [0] = 0 ; + if (stats [1] < 0) stats [1] = 0 ; + +} + +#endif diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_timer.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_timer.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_timer.c @@ -0,0 +1,83 @@ +/* ========================================================================== */ +/* === umfpack_timer ======================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User-callable. Returns the time in seconds used by the process. BE + CAREFUL: if you compare the run time of UMFPACK with other sparse matrix + packages, be sure to use the same timer. See umfpack_timer.h for details. + See umfpack_tictoc.h, which is the timer used internally by UMFPACK. +*/ + +#ifdef NO_TIMER + +/* -------------------------------------------------------------------------- */ +/* no timer used if -DNO_TIMER is defined at compile time */ +/* -------------------------------------------------------------------------- */ + +double umfpack_timer ( void ) +{ + return (0) ; +} + +#else + +#ifdef GETRUSAGE + +/* -------------------------------------------------------------------------- */ +/* use getrusage for accurate process times (and no overflow) */ +/* -------------------------------------------------------------------------- */ + +/* + This works under Solaris, SGI Irix, Linux, IBM RS 6000 (AIX), and Compaq + Alpha. It might work on other Unix systems, too. Includes both the "user + time" and the "system time". The system time is the time spent by the + operating system on behalf of the process, and thus should be charged to + the process. +*/ + +#include +#include + +double umfpack_timer ( void ) +{ + struct rusage ru ; + double user_time, sys_time ; + + (void) getrusage (RUSAGE_SELF, &ru) ; + + user_time = + ru.ru_utime.tv_sec /* user time (seconds) */ + + 1e-6 * ru.ru_utime.tv_usec ; /* user time (microseconds) */ + + sys_time = + ru.ru_stime.tv_sec /* system time (seconds) */ + + 1e-6 * ru.ru_stime.tv_usec ; /* system time (microseconds) */ + + return (user_time + sys_time) ; +} + +#else + +/* -------------------------------------------------------------------------- */ +/* Generic ANSI C: use the ANSI clock function */ +/* -------------------------------------------------------------------------- */ + +/* This is portable, but may overflow. On Sun Solaris, when compiling in */ +/* 32-bit mode, the overflow occurs in only 2147 seconds (about 36 minutes). */ + +#include + +double umfpack_timer ( void ) +{ + return (((double) (clock ( ))) / ((double) (CLOCKS_PER_SEC))) ; +} + +#endif +#endif diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_transpose.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_transpose.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_transpose.c @@ -0,0 +1,108 @@ +/* ========================================================================== */ +/* === UMFPACK_transpose ==================================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User callable. Computes a permuted transpose, R = (A (P,Q))' in MATLAB + notation. See umfpack_transpose.h for details. A and R can be rectangular. + The matrix A may be singular. + The complex version can do transpose (') or array transpose (.'). + + Dynamic memory usage: A single call to UMF_malloc is made, for a workspace + of size max (n_row,n_col,1) * sizeof(Int). This is then free'd on return, + via UMF_free. +*/ + +#include "umf_internal.h" +#include "umf_transpose.h" +#include "umf_malloc.h" +#include "umf_free.h" + +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif + +/* ========================================================================== */ + +GLOBAL Int UMFPACK_transpose +( + Int n_row, + Int n_col, + const Int Ap [ ], /* size n_col+1 */ + const Int Ai [ ], /* size nz = Ap [n_col] */ + const double Ax [ ], /* size nz, if present */ +#ifdef COMPLEX + const double Az [ ], /* size nz, if present */ +#endif + + const Int P [ ], /* P [k] = i means original row i is kth row in A(P,Q)*/ + /* P is identity if not present */ + /* size n_row, if present */ + + const Int Q [ ], /* Q [k] = j means original col j is kth col in A(P,Q)*/ + /* Q is identity if not present */ + /* size n_col, if present */ + + Int Rp [ ], /* size n_row+1 */ + Int Ri [ ], /* size nz */ + double Rx [ ] /* size nz, if present */ +#ifdef COMPLEX + , double Rz [ ] /* size nz, if present */ + , Int do_conjugate /* if true, then to conjugate transpose */ + /* otherwise, do array transpose */ +#endif +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int status, *W, nn ; + +#ifndef NDEBUG + init_count = UMF_malloc_count ; + UMF_dump_start ( ) ; +#endif + + /* ---------------------------------------------------------------------- */ + /* allocate workspace */ + /* ---------------------------------------------------------------------- */ + + nn = MAX (n_row, n_col) ; + nn = MAX (nn, 1) ; + W = (Int *) UMF_malloc (nn, sizeof (Int)) ; + if (!W) + { + DEBUGm4 (("out of memory: transpose work\n")) ; + ASSERT (UMF_malloc_count == init_count) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + ASSERT (UMF_malloc_count == init_count + 1) ; + + /* ---------------------------------------------------------------------- */ + /* C = (A (P,Q))' or (A (P,Q)).' */ + /* ---------------------------------------------------------------------- */ + + status = UMF_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, n_col, Rp, Ri, Rx, + W, TRUE +#ifdef COMPLEX + , Az, Rz, do_conjugate +#endif + ) ; + + /* ---------------------------------------------------------------------- */ + /* free the workspace */ + /* ---------------------------------------------------------------------- */ + + (void) UMF_free ((void *) W) ; + ASSERT (UMF_malloc_count == init_count) ; + + return (status) ; +} diff --git a/liboctave/UMFPACK/UMFPACK/Source/umfpack_triplet_to_col.c b/liboctave/UMFPACK/UMFPACK/Source/umfpack_triplet_to_col.c new file mode 100644 --- /dev/null +++ b/liboctave/UMFPACK/UMFPACK/Source/umfpack_triplet_to_col.c @@ -0,0 +1,225 @@ +/* ========================================================================== */ +/* === UMFPACK_triplet_to_col =============================================== */ +/* ========================================================================== */ + +/* -------------------------------------------------------------------------- */ +/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */ +/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */ +/* web: http://www.cise.ufl.edu/research/sparse/umfpack */ +/* -------------------------------------------------------------------------- */ + +/* + User callable. Converts triplet input to column-oriented form. Duplicate + entries may exist (they are summed in the output). The columns of the + column-oriented form are in sorted order. The input is not modified. + Returns 1 if OK, 0 if an error occurred. See umfpack_triplet_to_col.h for + details. + + If Map is present (a non-NULL pointer to an Int array of size nz), then on + output it holds the position of the triplets in the column-form matrix. + That is, suppose p = Map [k], and the k-th triplet is i=Ti[k], j=Tj[k], and + aij=Tx[k]. Then i=Ai[p], and aij will have been summed into Ax[p]. Also, + Ap[j] <= p < Ap[j+1]. The Map array is not computed if it is (Int *) NULL. + + Dynamic memory usage: + + If numerical values are present, then one (two for complex version) + workspace of size (nz+1)*sizeof(double) is allocated via UMF_malloc. + Next, 4 calls to UMF_malloc are made to obtain workspace of size + ((nz+1) + (n_row+1) + n_row + MAX (n_row,n_col)) * sizeof(Int). All of + this workspace (4 to 6 objects) are free'd via UMF_free on return. + + For the complex version, additional space is allocated. + + An extra array of size nz*sizeof(Int) is allocated if Map is present. +*/ + +#include "umf_internal.h" +#include "umf_malloc.h" +#include "umf_free.h" +#include "umf_triplet.h" + +#ifndef NDEBUG +PRIVATE Int init_count ; +#endif + +/* ========================================================================== */ + +GLOBAL Int UMFPACK_triplet_to_col +( + Int n_row, + Int n_col, + Int nz, + const Int Ti [ ], /* size nz */ + const Int Tj [ ], /* size nz */ + const double Tx [ ], /* size nz */ +#ifdef COMPLEX + const double Tz [ ], /* size nz */ +#endif + Int Ap [ ], /* size n_col + 1 */ + Int Ai [ ], /* size nz */ + double Ax [ ] /* size nz */ +#ifdef COMPLEX + , double Az [ ] /* size nz */ +#endif + , Int Map [ ] /* size nz */ +) +{ + + /* ---------------------------------------------------------------------- */ + /* local variables */ + /* ---------------------------------------------------------------------- */ + + Int *RowCount, *Rp, *Rj, *W, nn, do_values, do_map, *Map2, status ; + double *Rx ; +#ifdef COMPLEX + double *Rz ; + Int split ; +#endif + +#ifndef NDEBUG + UMF_dump_start ( ) ; + init_count = UMF_malloc_count ; +#endif + + /* ---------------------------------------------------------------------- */ + /* check inputs */ + /* ---------------------------------------------------------------------- */ + + if (!Ai || !Ap || !Ti || !Tj) + { + return (UMFPACK_ERROR_argument_missing) ; + } + + if (n_row <= 0 || n_col <= 0) /* must be > 0 */ + { + return (UMFPACK_ERROR_n_nonpositive) ; + } + + if (nz < 0) /* nz must be >= 0 (singular matrices are OK) */ + { + return (UMFPACK_ERROR_invalid_matrix) ; + } + + nn = MAX (n_row, n_col) ; + + /* ---------------------------------------------------------------------- */ + /* allocate workspace */ + /* ---------------------------------------------------------------------- */ + + Rx = (double *) NULL ; + + do_values = Ax && Tx ; + + if (do_values) + { +#ifdef COMPLEX + Rx = (double *) UMF_malloc (2*nz+2, sizeof (double)) ; + split = SPLIT (Tz) && SPLIT (Az) ; + if (split) + { + Rz = Rx + nz ; + } + else + { + Rz = (double *) NULL ; + } +#else + Rx = (double *) UMF_malloc (nz+1, sizeof (double)) ; +#endif + if (!Rx) + { + DEBUGm4 (("out of memory: triplet work \n")) ; + ASSERT (UMF_malloc_count == init_count) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + } + + do_map = (Map != (Int *) NULL) ; + Map2 = (Int *) NULL ; + if (do_map) + { + DEBUG0 (("Do map:\n")) ; + Map2 = (Int *) UMF_malloc (nz+1, sizeof (Int)) ; + if (!Map2) + { + DEBUGm4 (("out of memory: triplet map\n")) ; + (void) UMF_free ((void *) Rx) ; + ASSERT (UMF_malloc_count == init_count) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + } + + Rj = (Int *) UMF_malloc (nz+1, sizeof (Int)) ; + Rp = (Int *) UMF_malloc (n_row+1, sizeof (Int)) ; + RowCount = (Int *) UMF_malloc (n_row, sizeof (Int)) ; + W = (Int *) UMF_malloc (nn, sizeof (Int)) ; + if (!Rj || !Rp || !RowCount || !W) + { + DEBUGm4 (("out of memory: triplet work (int)\n")) ; + (void) UMF_free ((void *) Rx) ; + (void) UMF_free ((void *) Map2) ; + (void) UMF_free ((void *) Rp) ; + (void) UMF_free ((void *) Rj) ; + (void) UMF_free ((void *) RowCount) ; + (void) UMF_free ((void *) W) ; + ASSERT (UMF_malloc_count == init_count) ; + return (UMFPACK_ERROR_out_of_memory) ; + } + + ASSERT (UMF_malloc_count == init_count + 4 + + (Rx != (double *) NULL) + do_map) ; + + /* ---------------------------------------------------------------------- */ + /* convert from triplet to column form */ + /* ---------------------------------------------------------------------- */ + + if (do_map) + { + if (do_values) + { + status = UMF_triplet_map_x (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp, + Rj, W, RowCount, Tx, Ax, Rx +#ifdef COMPLEX + , Tz, Az, Rz +#endif + , Map, Map2) ; + } + else + { + status = UMF_triplet_map_nox (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp, + Rj, W, RowCount, Map, Map2) ; + } + } + else + { + if (do_values) + { + status = UMF_triplet_nomap_x (n_row, n_col, nz, Ti, Tj, Ap, Ai, Rp, + Rj, W, RowCount , Tx, Ax, Rx +#ifdef COMPLEX + , Tz, Az, Rz +#endif + ) ; + } + else + { + status = UMF_triplet_nomap_nox (n_row, n_col, nz, Ti, Tj, Ap, Ai, + Rp, Rj, W, RowCount) ; + } + } + + /* ---------------------------------------------------------------------- */ + /* free the workspace */ + /* ---------------------------------------------------------------------- */ + + (void) UMF_free ((void *) Rx) ; + (void) UMF_free ((void *) Map2) ; + (void) UMF_free ((void *) Rp) ; + (void) UMF_free ((void *) Rj) ; + (void) UMF_free ((void *) RowCount) ; + (void) UMF_free ((void *) W) ; + ASSERT (UMF_malloc_count == init_count) ; + + return (status) ; +} diff --git a/liboctave/boolSparse.cc b/liboctave/boolSparse.cc new file mode 100644 --- /dev/null +++ b/liboctave/boolSparse.cc @@ -0,0 +1,268 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "config.h" +#include "quit.h" +#include "lo-ieee.h" +#include "lo-mappers.h" + +#include "boolSparse.h" + +// SparseBoolMatrix class. + +bool +SparseBoolMatrix::operator == (const SparseBoolMatrix& a) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + int nr_a = a.rows (); + int nc_a = a.cols (); + int nz_a = a.nnz (); + + if (nr != nr_a || nc != nc_a || nz != nz_a) + return false; + + for (int i = 0; i < nc + 1; i++) + if (cidx(i) != a.cidx(i)) + return false; + + for (int i = 0; i < nz; i++) + if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) + return false; + + return true; +} + +bool +SparseBoolMatrix::operator != (const SparseBoolMatrix& a) const +{ + return !(*this == a); +} + +SparseBoolMatrix& +SparseBoolMatrix::insert (const SparseBoolMatrix& a, int r, int c) +{ + Sparse::insert (a, r, c); + return *this; +} + +SparseBoolMatrix +SparseBoolMatrix::concat (const SparseBoolMatrix& rb, const Array& ra_idx) +{ + // Don't use numel to avoid all possiblity of an overflow + if (rb.rows () > 0 && rb.cols () > 0) + insert (rb, ra_idx(0), ra_idx(1)); + return *this; +} + +// unary operations + +SparseBoolMatrix +SparseBoolMatrix::operator ! (void) const +{ + int nr = rows (); + int nc = cols (); + int nz1 = nnz (); + int nz2 = nr*nc - nz1; + + SparseBoolMatrix r (nr, nc, nz2); + + int ii = 0; + int jj = 0; + for (int i = 0; i < nc; i++) + { + for (int j = 0; j < nr; j++) + { + if (jj < cidx(i+1) && ridx(jj) == j) + jj++; + else + { + r.data(ii) = true; + r.ridx(ii++) = j; + } + } + r.cidx (i) = ii; + } + + return r; +} + +// other operations + +// XXX FIXME XXX Do these really belong here? Maybe they should be +// in a base class? + +SparseBoolMatrix +SparseBoolMatrix::all (int dim) const +{ + SPARSE_ALL_OP (dim); +} + +SparseBoolMatrix +SparseBoolMatrix::any (int dim) const +{ + SPARSE_ANY_OP (dim); +} + +boolMatrix +SparseBoolMatrix::matrix_value (void) const +{ + int nr = rows (); + int nc = cols (); + + boolMatrix retval (nr, nc, false); + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + retval.elem (ridx(i), j) = data (i); + + return retval; +} + +std::ostream& +operator << (std::ostream& os, const SparseBoolMatrix& a) +{ + int nc = a.cols (); + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int j = 0; j < nc; j++) + { + OCTAVE_QUIT; + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + os << a.ridx(i) + 1 << " " << j + 1 << " " << a.data(i) << "\n"; + } + + return os; +} + +std::istream& +operator >> (std::istream& is, SparseBoolMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + + if (nr < 1 || nc < 1) + is.clear (std::ios::badbit); + else + { + int itmp, jtmp, jold = 0; + bool tmp; + int ii = 0; + + a.cidx (0) = 0; + for (int i = 0; i < nz; i++) + { + is >> itmp; + itmp--; + is >> jtmp; + jtmp--; + is >> tmp; + if (is) + { + if (jold != jtmp) + { + for (int j = jold; j < jtmp; j++) + a.cidx(j+1) = ii; + + jold = jtmp; + } + a.data (ii) = tmp; + a.ridx (ii++) = itmp; + } + else + goto done; + } + + for (int j = jold; j < nc; j++) + a.cidx(j+1) = ii; + } + + done: + + return is; +} + +SparseBoolMatrix +SparseBoolMatrix::squeeze (void) const +{ + return Sparse::squeeze (); +} + +SparseBoolMatrix +SparseBoolMatrix::index (idx_vector& i, int resize_ok) const +{ + return Sparse::index (i, resize_ok); +} + +SparseBoolMatrix +SparseBoolMatrix::index (idx_vector& i, idx_vector& j, int resize_ok) const +{ + return Sparse::index (i, j, resize_ok); +} + +SparseBoolMatrix +SparseBoolMatrix::index (Array& ra_idx, int resize_ok) const +{ + return Sparse::index (ra_idx, resize_ok); +} + +SparseBoolMatrix +SparseBoolMatrix::reshape (const dim_vector& new_dims) const +{ + return Sparse::reshape (new_dims); +} + +SparseBoolMatrix +SparseBoolMatrix::permute (const Array& vec, bool inv) const +{ + return Sparse::permute (vec, inv); +} + +SparseBoolMatrix +SparseBoolMatrix::ipermute (const Array& vec) const +{ + return Sparse::ipermute (vec); +} + +SPARSE_SMS_EQNE_OPS (SparseBoolMatrix, false, , bool, false, ) +SPARSE_SMS_BOOL_OPS (SparseBoolMatrix, bool, false) + +SPARSE_SSM_EQNE_OPS (bool, false, , SparseBoolMatrix, false, ) +SPARSE_SSM_BOOL_OPS (bool, SparseBoolMatrix, false) + +SPARSE_SMSM_EQNE_OPS (SparseBoolMatrix, false, , SparseBoolMatrix, false, ) +SPARSE_SMSM_BOOL_OPS (SparseBoolMatrix, SparseBoolMatrix, false) + + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/boolSparse.h b/liboctave/boolSparse.h new file mode 100644 --- /dev/null +++ b/liboctave/boolSparse.h @@ -0,0 +1,129 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_boolSparse_h) +#define octave_boolSparse_h 1 + +#include "Sparse.h" +#include "MSparse-defs.h" +#include "Sparse-op-defs.h" + +class +SparseBoolMatrix : public Sparse +{ +public: + + SparseBoolMatrix (void) : Sparse () { } + + SparseBoolMatrix (int r, int c) : Sparse (r, c) { } + + explicit SparseBoolMatrix (int r, int c, bool val) + : Sparse (r, c, val) { } + + SparseBoolMatrix (const Sparse& a) : Sparse (a) { } + + SparseBoolMatrix (const SparseBoolMatrix& a) : Sparse (a) { } + + SparseBoolMatrix (const SparseBoolMatrix& a, const dim_vector& dv) + : Sparse (a, dv) { } + + explicit SparseBoolMatrix (const boolMatrix& a) : Sparse (a) { } + + explicit SparseBoolMatrix (const boolNDArray& a) : Sparse (a) { } + + explicit SparseBoolMatrix (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : Sparse (a, r, c, nr, nc, sum_terms) { } + + explicit SparseBoolMatrix (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : Sparse (a, r, c, nr, nc, sum_terms) { } + + SparseBoolMatrix (int r, int c, int num_nz) : Sparse (r, c, num_nz) { } + + SparseBoolMatrix& operator = (const SparseBoolMatrix& a) + { + Sparse::operator = (a); + return *this; + } + + bool operator == (const SparseBoolMatrix& a) const; + bool operator != (const SparseBoolMatrix& a) const; + + SparseBoolMatrix transpose (void) const + { return Sparse::transpose (); } + + // destructive insert/delete/reorder operations + + SparseBoolMatrix& insert (const SparseBoolMatrix& a, int r, int c); + + SparseBoolMatrix concat (const SparseBoolMatrix& rb, + const Array& ra_idx); + + boolMatrix matrix_value (void) const; + + SparseBoolMatrix squeeze (void) const; + + SparseBoolMatrix index (idx_vector& i, int resize_ok) const; + + SparseBoolMatrix index (idx_vector& i, idx_vector& j, int resize_ok) const; + + SparseBoolMatrix index (Array& ra_idx, int resize_ok) const; + + SparseBoolMatrix reshape (const dim_vector& new_dims) const; + + SparseBoolMatrix permute (const Array& vec, bool inv = false) const; + + SparseBoolMatrix ipermute (const Array& vec) const; + + // unary operations + + SparseBoolMatrix operator ! (void) const; + + // other operations + + SparseBoolMatrix all (int dim = -1) const; + SparseBoolMatrix any (int dim = -1) const; + + // i/o + + friend std::ostream& operator << (std::ostream& os, const SparseBoolMatrix& a); + friend std::istream& operator >> (std::istream& is, SparseBoolMatrix& a); +}; + +SPARSE_SMS_EQNE_OP_DECLS (SparseBoolMatrix, bool) +SPARSE_SMS_BOOL_OP_DECLS (SparseBoolMatrix, bool) + +SPARSE_SSM_EQNE_OP_DECLS (bool, SparseBoolMatrix) +SPARSE_SSM_BOOL_OP_DECLS (bool, SparseBoolMatrix) + +SPARSE_SMSM_EQNE_OP_DECLS (SparseBoolMatrix, SparseBoolMatrix) +SPARSE_SMSM_BOOL_OP_DECLS (SparseBoolMatrix, SparseBoolMatrix) + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/dNDArray.cc b/liboctave/dNDArray.cc --- a/liboctave/dNDArray.cc +++ b/liboctave/dNDArray.cc @@ -26,6 +26,7 @@ #endif #include + #include #include "Array-util.h" diff --git a/liboctave/dSparse.cc b/liboctave/dSparse.cc new file mode 100644 --- /dev/null +++ b/liboctave/dSparse.cc @@ -0,0 +1,6713 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "quit.h" +#include "lo-ieee.h" +#include "lo-mappers.h" +#include "f77-fcn.h" +#include "dRowVector.h" + +#include "CSparse.h" +#include "boolSparse.h" +#include "dSparse.h" +#include "oct-spparms.h" +#include "SparsedbleLU.h" +#include "SparseType.h" + +// External UMFPACK functions in C +extern "C" { +#include "umfpack.h" +} + +// Fortran functions we call. +extern "C" +{ + F77_RET_T + F77_FUNC (dgbtrf, DGBTRF) (const int&, const int&, const int&, + const int&, double*, const int&, int*, int&); + + F77_RET_T + F77_FUNC (dgbtrs, DGBTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, const int&, + const double*, const int&, + const int*, double*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (dgbcon, DGBCON) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, double*, + const int&, const int*, const double&, + double&, double*, int*, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (dpbtrf, DPBTRF) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, double*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (dpbtrs, DPBTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const int&, double*, const int&, + double*, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (dpbcon, DPBCON) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, double*, const int&, + const double&, double&, double*, int*, int& + F77_CHAR_ARG_LEN_DECL); + F77_RET_T + F77_FUNC (dptsv, DPTSV) (const int&, const int&, double*, double*, + double*, const int&, int&); + + F77_RET_T + F77_FUNC (dgtsv, DGTSV) (const int&, const int&, double*, double*, + double*, double*, const int&, int&); + + F77_RET_T + F77_FUNC (dgttrf, DGTTRF) (const int&, double*, double*, double*, double*, + int*, int&); + + F77_RET_T + F77_FUNC (dgttrs, DGTTRS) (F77_CONST_CHAR_ARG_DECL, const int&, + const int&, const double*, const double*, + const double*, const double*, const int*, + double *, const int&, int& + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zptsv, ZPTSV) (const int&, const int&, Complex*, Complex*, + Complex*, const int&, int&); + + F77_RET_T + F77_FUNC (zgtsv, ZGTSV) (const int&, const int&, Complex*, Complex*, + Complex*, Complex*, const int&, int&); + +} + +SparseMatrix::SparseMatrix (const SparseBoolMatrix &a) + : MSparse (a.rows (), a.cols (), a.nnz ()) +{ + int nc = cols (); + int nz = nnz (); + + for (int i = 0; i < nc + 1; i++) + cidx (i) = a.cidx (i); + + for (int i = 0; i < nz; i++) + { + data (i) = a.data (i); + ridx (i) = a.ridx (i); + } +} + +bool +SparseMatrix::operator == (const SparseMatrix& a) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + int nr_a = a.rows (); + int nc_a = a.cols (); + int nz_a = a.nnz (); + + if (nr != nr_a || nc != nc_a || nz != nz_a) + return false; + + for (int i = 0; i < nc + 1; i++) + if (cidx(i) != a.cidx(i)) + return false; + + for (int i = 0; i < nz; i++) + if (data(i) != a.data(i) || ridx(i) != a.ridx(i)) + return false; + + return true; +} + +bool +SparseMatrix::operator != (const SparseMatrix& a) const +{ + return !(*this == a); +} + +bool +SparseMatrix::is_symmetric (void) const +{ + if (is_square () && rows () > 0) + { + for (int i = 0; i < rows (); i++) + for (int j = i+1; j < cols (); j++) + if (elem (i, j) != elem (j, i)) + return false; + + return true; + } + + return false; +} + +SparseMatrix& +SparseMatrix::insert (const SparseMatrix& a, int r, int c) +{ + MSparse::insert (a, r, c); + return *this; +} + +SparseMatrix +SparseMatrix::max (int dim) const +{ + Array2 dummy_idx; + return max (dummy_idx, dim); +} + +SparseMatrix +SparseMatrix::max (Array2& idx_arg, int dim) const +{ + SparseMatrix result; + dim_vector dv = dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return result; + + int nr = dv(0); + int nc = dv(1); + + if (dim == 0) + { + idx_arg.resize (1, nc); + int nel = 0; + for (int j = 0; j < nc; j++) + { + double tmp_max = octave_NaN; + int idx_j = 0; + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) != idx_j) + break; + else + idx_j++; + } + + if (idx_j != nr) + tmp_max = 0.; + + for (int i = cidx(j); i < cidx(j+1); i++) + { + double tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (octave_is_NaN_or_NA (tmp_max) || tmp > tmp_max) + { + idx_j = ridx (i); + tmp_max = tmp; + } + + } + + idx_arg.elem (j) = octave_is_NaN_or_NA (tmp_max) ? 0 : idx_j; + if (tmp_max != 0.) + nel++; + } + + result = SparseMatrix (1, nc, nel); + + int ii = 0; + result.xcidx (0) = 0; + for (int j = 0; j < nc; j++) + { + double tmp = elem (idx_arg(j), j); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = 0; + } + result.xcidx (j+1) = ii; + + } + } + else + { + idx_arg.resize (nr, 1, 0); + + for (int i = cidx(0); i < cidx(1); i++) + idx_arg.elem(ridx(i)) = -1; + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (idx_arg.elem(i) != -1) + continue; + bool found = false; + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + found = true; + break; + } + + if (!found) + idx_arg.elem(i) = j; + + } + + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ir = ridx (i); + int ix = idx_arg.elem (ir); + double tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (ix == -1 || tmp > elem (ir, ix)) + idx_arg.elem (ir) = j; + } + } + + int nel = 0; + for (int j = 0; j < nr; j++) + if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) + nel++; + + result = SparseMatrix (nr, 1, nel); + + int ii = 0; + result.xcidx (0) = 0; + result.xcidx (1) = nel; + for (int j = 0; j < nr; j++) + { + if (idx_arg(j) == -1) + { + idx_arg(j) = 0; + result.xdata (ii) = octave_NaN; + result.xridx (ii++) = j; + } + else + { + double tmp = elem (j, idx_arg(j)); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = j; + } + } + } + } + + return result; +} + +SparseMatrix +SparseMatrix::min (int dim) const +{ + Array2 dummy_idx; + return min (dummy_idx, dim); +} + +SparseMatrix +SparseMatrix::min (Array2& idx_arg, int dim) const +{ + SparseMatrix result; + dim_vector dv = dims (); + + if (dv.numel () == 0 || dim > dv.length () || dim < 0) + return result; + + int nr = dv(0); + int nc = dv(1); + + if (dim == 0) + { + idx_arg.resize (1, nc); + int nel = 0; + for (int j = 0; j < nc; j++) + { + double tmp_min = octave_NaN; + int idx_j = 0; + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) != idx_j) + break; + else + idx_j++; + } + + if (idx_j != nr) + tmp_min = 0.; + + for (int i = cidx(j); i < cidx(j+1); i++) + { + double tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (octave_is_NaN_or_NA (tmp_min) || tmp < tmp_min) + { + idx_j = ridx (i); + tmp_min = tmp; + } + + } + + idx_arg.elem (j) = octave_is_NaN_or_NA (tmp_min) ? 0 : idx_j; + if (tmp_min != 0.) + nel++; + } + + result = SparseMatrix (1, nc, nel); + + int ii = 0; + result.xcidx (0) = 0; + for (int j = 0; j < nc; j++) + { + double tmp = elem (idx_arg(j), j); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = 0; + } + result.xcidx (j+1) = ii; + + } + } + else + { + idx_arg.resize (nr, 1, 0); + + for (int i = cidx(0); i < cidx(1); i++) + idx_arg.elem(ridx(i)) = -1; + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (idx_arg.elem(i) != -1) + continue; + bool found = false; + for (int k = cidx(j); k < cidx(j+1); k++) + if (ridx(k) == i) + { + found = true; + break; + } + + if (!found) + idx_arg.elem(i) = j; + + } + + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ir = ridx (i); + int ix = idx_arg.elem (ir); + double tmp = data (i); + + if (octave_is_NaN_or_NA (tmp)) + continue; + else if (ix == -1 || tmp < elem (ir, ix)) + idx_arg.elem (ir) = j; + } + } + + int nel = 0; + for (int j = 0; j < nr; j++) + if (idx_arg.elem(j) == -1 || elem (j, idx_arg.elem (j)) != 0.) + nel++; + + result = SparseMatrix (nr, 1, nel); + + int ii = 0; + result.xcidx (0) = 0; + result.xcidx (1) = nel; + for (int j = 0; j < nr; j++) + { + if (idx_arg(j) == -1) + { + idx_arg(j) = 0; + result.xdata (ii) = octave_NaN; + result.xridx (ii++) = j; + } + else + { + double tmp = elem (j, idx_arg(j)); + if (tmp != 0.) + { + result.xdata (ii) = tmp; + result.xridx (ii++) = j; + } + } + } + } + + return result; +} + +SparseMatrix +SparseMatrix::concat (const SparseMatrix& rb, const Array& ra_idx) +{ + // Don't use numel to avoid all possiblity of an overflow + if (rb.rows () > 0 && rb.cols () > 0) + insert (rb, ra_idx(0), ra_idx(1)); + return *this; +} + +SparseComplexMatrix +SparseMatrix::concat (const SparseComplexMatrix& rb, const Array& ra_idx) +{ + SparseComplexMatrix retval (*this); + if (rb.rows () > 0 && rb.cols () > 0) + retval.insert (rb, ra_idx(0), ra_idx(1)); + return retval; +} + +SparseMatrix +real (const SparseComplexMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + SparseMatrix r (nr, nc, nz); + + for (int i = 0; i < nc +1; i++) + r.cidx(i) = a.cidx(i); + + for (int i = 0; i < nz; i++) + { + r.data(i) = real (a.data(i)); + r.ridx(i) = a.ridx(i); + } + + return r; +} + +SparseMatrix +imag (const SparseComplexMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + SparseMatrix r (nr, nc, nz); + + for (int i = 0; i < nc +1; i++) + r.cidx(i) = a.cidx(i); + + for (int i = 0; i < nz; i++) + { + r.data(i) = imag (a.data(i)); + r.ridx(i) = a.ridx(i); + } + + return r; +} + +SparseMatrix +atan2 (const double& x, const SparseMatrix& y) +{ + int nr = y.rows (); + int nc = y.cols (); + + if (x == 0.) + return SparseMatrix (nr, nc); + else + { + // Its going to be basically full, so this is probably the + // best way to handle it. + Matrix tmp (nr, nc, atan2 (x, 0.)); + + for (int j = 0; j < nc; j++) + for (int i = y.cidx (j); i < y.cidx (j+1); i++) + tmp.elem (y.ridx(i), j) = atan2 (x, y.data(i)); + + return SparseMatrix (tmp); + } +} + +SparseMatrix +atan2 (const SparseMatrix& x, const double& y) +{ + int nr = x.rows (); + int nc = x.cols (); + int nz = x.nnz (); + + SparseMatrix retval (nr, nc, nz); + + int ii = 0; + retval.xcidx(0) = 0; + for (int i = 0; i < nc; i++) + { + for (int j = x.cidx(i); j < x.cidx(i+1); j++) + { + double tmp = atan2 (x.data(j), y); + if (tmp != 0.) + { + retval.xdata (ii) = tmp; + retval.xridx (ii++) = x.ridx (j); + } + } + retval.xcidx (i+1) = ii; + } + + if (ii != nz) + { + SparseMatrix retval2 (nr, nc, ii); + for (int i = 0; i < nc+1; i++) + retval2.xcidx (i) = retval.cidx (i); + for (int i = 0; i < ii; i++) + { + retval2.xdata (i) = retval.data (i); + retval2.xridx (i) = retval.ridx (i); + } + return retval2; + } + else + return retval; +} + +SparseMatrix +atan2 (const SparseMatrix& x, const SparseMatrix& y) +{ + SparseMatrix r; + + if ((x.rows() == y.rows()) && (x.cols() == y.cols())) + { + int x_nr = x.rows (); + int x_nc = x.cols (); + + int y_nr = y.rows (); + int y_nc = y.cols (); + + if (x_nr != y_nr || x_nc != y_nc) + gripe_nonconformant ("atan2", x_nr, x_nc, y_nr, y_nc); + else + { + r = SparseMatrix (x_nr, x_nc, (x.nnz () + y.nnz ())); + + int jx = 0; + r.cidx (0) = 0; + for (int i = 0 ; i < x_nc ; i++) + { + int ja = x.cidx(i); + int ja_max = x.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = y.cidx(i); + int jb_max = y.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (x.ridx(ja) < y.ridx(jb)))) + { + r.ridx(jx) = x.ridx(ja); + r.data(jx) = atan2 (x.data(ja), 0.); + jx++; + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (y.ridx(jb) < x.ridx(ja)) ) ) + { + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = atan2 (x.data(ja), y.data(jb)); + if (tmp != 0.) + { + r.data(jx) = tmp; + r.ridx(jx) = x.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + r.maybe_compress (); + } + } + else + (*current_liboctave_error_handler) ("matrix size mismatch"); + + return r; +} + +SparseMatrix +SparseMatrix::inverse (void) const +{ + int info; + double rcond; + return inverse (info, rcond, 0, 0); +} + +SparseMatrix +SparseMatrix::inverse (int& info) const +{ + double rcond; + return inverse (info, rcond, 0, 0); +} + +SparseMatrix +SparseMatrix::inverse (int& info, double& rcond, int force, int calc_cond) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseMatrix::inverse not implemented yet"); + return SparseMatrix (); +} + +DET +SparseMatrix::determinant (void) const +{ + int info; + double rcond; + return determinant (info, rcond, 0); +} + +DET +SparseMatrix::determinant (int& info) const +{ + double rcond; + return determinant (info, rcond, 0); +} + +DET +SparseMatrix::determinant (int& err, double& rcond, int) const +{ + DET retval; + + int nr = rows (); + int nc = cols (); + + if (nr == 0 || nc == 0 || nr != nc) + { + double d[2]; + d[0] = 1.0; + d[1] = 0.0; + retval = DET (d); + } + else + { + err = 0; + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_di_report_control (control); + + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, NULL, + &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::determinant symbolic factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + + rcond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::determinant numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + umfpack_di_report_numeric (Numeric, control); + + double d[2]; + + status = umfpack_di_get_determinant (&d[0], &d[1], Numeric, + info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::determinant error calculating determinant"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + retval = DET (d); + } + } + } + + return retval; +} + +Matrix +SparseMatrix::dsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, solve_singularity_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + retval.resize (b.rows (), b.cols()); + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(i,j) / data (i); + else + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(ridx(i),j) / data (i); + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::dsolve (SparseType &mattype, const SparseMatrix& b, int& err, + double& rcond, solve_singularity_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseMatrix (b_nr, b_nc, b_nz); + + retval.xcidx(0) = 0; + int ii = 0; + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + { + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + retval.xridx (ii) = b.ridx(i); + retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); + } + retval.xcidx(j+1) = ii; + } + else + for (int j = 0; j < b.cols(); j++) + { + for (int i = 0; i < nr; i++) + { + bool found = false; + int k; + for (k = b.cidx(j); k < b.cidx(j+1); k++) + if (ridx(i) == b.ridx(k)) + { + found = true; + break; + } + if (found) + { + retval.xridx (ii) = i; + retval.xdata (ii++) = b.data(k) / data (i); + } + } + retval.xcidx(j+1) = ii; + } + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseMatrix::dsolve (SparseType &mattype, const ComplexMatrix& b, int& err, + double& rcond, solve_singularity_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + retval.resize (b.rows (), b.cols()); + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(i,j) / data (i); + else + for (int j = 0; j < b.cols(); j++) + for (int i = 0; i < nr; i++) + retval(i,j) = b(ridx(i),j) / data (i); + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::dsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Diagonal || + typ == SparseType::Permuted_Diagonal) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + + retval.xcidx(0) = 0; + int ii = 0; + if (typ == SparseType::Diagonal) + for (int j = 0; j < b.cols(); j++) + { + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + retval.xridx (ii) = b.ridx(i); + retval.xdata (ii++) = b.data(i) / data (b.ridx (i)); + } + retval.xcidx(j+1) = ii; + } + else + for (int j = 0; j < b.cols(); j++) + { + for (int i = 0; i < nr; i++) + { + bool found = false; + int k; + for (k = b.cidx(j); k < b.cidx(j+1); k++) + if (ridx(i) == b.ridx(k)) + { + found = true; + break; + } + if (found) + { + retval.xridx (ii) = i; + retval.xdata (ii++) = b.data(k) / data (i); + } + } + retval.xcidx(j+1) = ii; + } + + double dmax = 0., dmin = octave_Inf; + for (int i = 0; i < nr; i++) + { + double tmp = fabs(data(i)); + if (tmp > dmax) + dmax = tmp; + if (tmp < dmin) + dmin = tmp; + } + rcond = dmin / dmax; + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +Matrix +SparseMatrix::utsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_cols = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Upper) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (double, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_cols; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + double *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_cols; j++) + { + int offset = j * nr; + for (int k = nr-1; k >= 0; k--) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + double tmp = x_vec[k+offset] / + data(cidx(k+1)-1); + x_vec[k+offset] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::utsolve (SparseType &mattype, const SparseMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Upper) + { + OCTAVE_LOCAL_BUFFER (double, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (double, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + if (work[k] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + return retval; +} + +ComplexMatrix +SparseMatrix::utsolve (SparseType &mattype, const ComplexMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_nc = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Upper) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work2, nr); + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work2[iidx] != 0.) + { + double tmp = work2[iidx] / data(cidx(iidx+1)-1); + work2[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work2[idx2] = work2[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_nc; j++) + { + int offset = j * nr; + for (int k = nr-1; k >= 0; k--) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k+1)-1); + x_vec[k+offset] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::utsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Upper || + typ == SparseType::Upper) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Upper) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx+1)-1) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + OCTAVE_LOCAL_BUFFER (double, work2, nr); + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[q_perm[j]] = 1.; + + for (int k = j; k >= 0; k--) + { + int iidx = q_perm[k]; + + if (work2[iidx] != 0.) + { + double tmp = work2[iidx] / data(cidx(iidx+1)-1); + work2[iidx] = tmp; + for (int i = cidx(iidx); i < cidx(iidx+1)-1; i++) + { + int idx2 = q_perm[ridx(i)]; + work2[idx2] = work2[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = nr-1; k >= 0; k--) + { + if (work[k] != 0.) + { + if (ridx(cidx(k+1)-1) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k+1)-1); + work[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work2, nr); + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[j] = 1.; + + for (int k = j; k >= 0; k--) + { + if (work2[k] != 0.) + { + double tmp = work2[k] / data(cidx(k+1)-1); + work2[k] = tmp; + for (int i = cidx(k); i < cidx(k+1)-1; i++) + { + int iidx = ridx(i); + work2[iidx] = work2[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +Matrix +SparseMatrix::ltsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_cols = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Lower) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (double, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_cols; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + double *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_cols; j++) + { + int offset = j * nr; + for (int k = 0; k < nr; k++) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + double tmp = x_vec[k+offset] / + data(cidx(k)); + x_vec[k+offset] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::ltsolve (SparseType &mattype, const SparseMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Lower) + { + OCTAVE_LOCAL_BUFFER (double, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work[iidx] != 0.) + { + double tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = work[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (double, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + if (work[k] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseMatrix::ltsolve (SparseType &mattype, const ComplexMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + int b_nc = b.cols (); + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + if (typ == SparseType::Permuted_Lower) + { + retval.resize (b.rows (), b.cols ()); + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = b(i,j); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + for (int i = 0; i < nr; i++) + retval (i, j) = work[p_perm[i]]; + + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work2, nr); + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work2[iidx] != 0.) + { + double tmp = work2[iidx] / data(cidx(iidx+1)-1); + work2[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work2[idx2] = work2[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + retval = b; + Complex *x_vec = retval.fortran_vec (); + + for (int j = 0; j < b_nc; j++) + { + int offset = j * nr; + for (int k = 0; k < nr; k++) + { + if (x_vec[k+offset] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = x_vec[k+offset] / + data(cidx(k)); + x_vec[k+offset] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + x_vec[iidx+offset] = + x_vec[iidx+offset] - tmp * data(i); + } + } + } + } + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work, nr); + for (int i = 0; i < nr; i++) + work[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work[k] != 0.) + { + double tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += fabs(work[i]); + work[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::ltsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Permuted_Lower || + typ == SparseType::Lower) + { + double anorm = 0.; + double ainvnorm = 0.; + rcond = 0.; + + // Calculate the 1-norm of matrix for rcond calculation + for (int j = 0; j < nr; j++) + { + double atmp = 0.; + for (int i = cidx(j); i < cidx(j+1); i++) + atmp += fabs(data(i)); + if (atmp > anorm) + anorm = atmp; + } + + int b_nr = b.rows (); + int b_nc = b.cols (); + int b_nz = b.nnz (); + retval = SparseComplexMatrix (b_nr, b_nc, b_nz); + retval.xcidx(0) = 0; + int ii = 0; + int x_nz = b_nz; + + if (typ == SparseType::Permuted_Lower) + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + int *p_perm = mattype.triangular_row_perm (); + int *q_perm = mattype.triangular_col_perm (); + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX permuted triangular code not tested"); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + if (work[iidx] != 0.) + { + if (ridx(cidx(iidx)) != iidx) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[iidx] / data(cidx(iidx+1)-1); + work[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work[idx2] = + work[idx2] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[p_perm[i]] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[p_perm[i]]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work2, nr); + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[q_perm[j]] = 1.; + + for (int k = 0; k < nr; k++) + { + int iidx = q_perm[k]; + + if (work2[iidx] != 0.) + { + double tmp = work2[iidx] / data(cidx(iidx+1)-1); + work2[iidx] = tmp; + for (int i = cidx(iidx)+1; i < cidx(iidx+1); i++) + { + int idx2 = q_perm[ridx(i)]; + work2[idx2] = work2[idx2] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = 0; i < j+1; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + } + else + { + OCTAVE_LOCAL_BUFFER (Complex, work, nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + for (int k = 0; k < nr; k++) + { + if (work[k] != 0.) + { + if (ridx(cidx(k)) != k) + { + err = -2; + goto triangular_error; + } + + Complex tmp = work[k] / data(cidx(k)); + work[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work[iidx] = work[iidx] - tmp * data(i); + } + } + } + + // Count non-zeros in work vector and adjust space in + // retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + + // Calculation of 1-norm of inv(*this) + OCTAVE_LOCAL_BUFFER (double, work2, nr); + for (int i = 0; i < nr; i++) + work2[i] = 0.; + + for (int j = 0; j < nr; j++) + { + work2[j] = 1.; + + for (int k = j; k < nr; k++) + { + + if (work2[k] != 0.) + { + double tmp = work2[k] / data(cidx(k)); + work2[k] = tmp; + for (int i = cidx(k)+1; i < cidx(k+1); i++) + { + int iidx = ridx(i); + work2[iidx] = work2[iidx] - tmp * data(i); + } + } + } + double atmp = 0; + for (int i = j; i < nr; i++) + { + atmp += fabs(work2[i]); + work2[i] = 0.; + } + if (atmp > ainvnorm) + ainvnorm = atmp; + } + + } + + rcond = 1. / ainvnorm / anorm; + + triangular_error: + if (err != 0) + { + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + } + + volatile double rcond_plus_one = rcond + 1.0; + + if (rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision, rcond = %g", + rcond); + } + } + else + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +Matrix +SparseMatrix::trisolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (double, D, nr); + OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii); + ii += 2; + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + } + } + + int b_nc = b.cols(); + retval = b; + double *result = retval.fortran_vec (); + + F77_XFCN (dptsv, DPTSV, (nr, b_nc, D, DL, result, + b.rows(), err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dptsv"); + else if (err != 0) + { + err = 0; + mattype.mark_as_unsymmetric (); + typ = SparseType::Tridiagonal; + } + else + rcond = 1.; + } + + if (typ == SparseType::Tridiagonal) + { + OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (double, D, nr); + OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + int b_nc = b.cols(); + retval = b; + double *result = retval.fortran_vec (); + + F77_XFCN (dgtsv, DGTSV, (nr, b_nc, DL, D, DU, result, + b.rows(), err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgtsv"); + else if (err != 0) + { + rcond = 0.; + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + rcond = 1.; + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::trisolve (SparseType &mattype, const SparseMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2); + OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (double, D, nr); + OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + F77_XFCN (dgttrf, DGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgttrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (double, work, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (dgttrs, DGTTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, 1, DL, D, DU, DU2, pipvt, + work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgttrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseMatrix::trisolve (SparseType &mattype, const ComplexMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii); + ii += 2; + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + } + } + + int b_nr = b.rows (); + int b_nc = b.cols(); + rcond = 1.; + + retval = b; + Complex *result = retval.fortran_vec (); + + F77_XFCN (zptsv, ZPTSV, (nr, b_nc, D, DL, result, + b_nr, err)); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zptsv"); + err = -1; + } + else if (err != 0) + { + err = 0; + mattype.mark_as_unsymmetric (); + typ = SparseType::Tridiagonal; + } + } + + if (typ == SparseType::Tridiagonal) + { + OCTAVE_LOCAL_BUFFER (Complex, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (Complex, D, nr); + OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + int b_nr = b.rows(); + int b_nc = b.cols(); + rcond = 1.; + + retval = b; + Complex *result = retval.fortran_vec (); + + F77_XFCN (zgtsv, ZGTSV, (nr, b_nc, DL, D, DU, result, + b_nr, err)); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in zgtsv"); + err = -1; + } + else if (err != 0) + { + rcond = 0.; + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::trisolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + // Note can't treat symmetric case as there is no dpttrf function + if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + { + OCTAVE_LOCAL_BUFFER (double, DU2, nr - 2); + OCTAVE_LOCAL_BUFFER (double, DU, nr - 1); + OCTAVE_LOCAL_BUFFER (double, D, nr); + OCTAVE_LOCAL_BUFFER (double, DL, nr - 1); + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + if (mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < nc-1; j++) + { + D[j] = data(ii++); + DL[j] = data(ii++); + DU[j] = data(ii++); + } + D[nc-1] = data(ii); + } + else + { + D[0] = 0.; + for (int i = 0; i < nr - 1; i++) + { + D[i+1] = 0.; + DL[i] = 0.; + DU[i] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + if (ridx(i) == j) + D[j] = data(i); + else if (ridx(i) == j + 1) + DL[j] = data(i); + else if (ridx(i) == j - 1) + DU[j] = data(i); + } + } + + F77_XFCN (dgttrf, DGTTRF, (nr, DL, D, DU, DU2, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgttrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + } + else + { + rcond = 1.; + char job = 'N'; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + + F77_XFCN (dgttrs, DGTTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, 1, DL, D, DU, DU2, pipvt, + Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgttrs"); + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + err = -1; + break; + } + + F77_XFCN (dgttrs, DGTTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, 1, DL, D, DU, DU2, pipvt, + Bz, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgttrs"); + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + err = -1; + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = + Complex (Bx[i], Bz[i]); + } + + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Tridiagonal_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +Matrix +SparseMatrix::bsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + // Calculate the norm of the matrix, for later use. + // double anorm = m_band.abs().sum().row(0).max(); + + char job = 'L'; + F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + // Unfortunately, the time to calculate the condition + // number is dominant for narrow banded matrices and + // so we rely on the "err" flag from xPBTRF to flag + // singularity. The commented code below is left here + // for reference + + //Array z (3 * nr); + //double *pz = z.fortran_vec (); + //Array iz (nr); + //int *piz = iz.fortran_vec (); + // + //F77_XFCN (dpbcon, DGBCON, + // (F77_CONST_CHAR_ARG2 (&job, 1), + // nr, n_lower, tmp_data, ldm, + // anorm, rcond, pz, piz, err + // F77_CHAR_ARG_LEN (1))); + // + // + //if (f77_exception_encountered) + // (*current_liboctave_error_handler) + // ("unrecoverable error in dpbcon"); + // + //if (err != 0) + // err = -2; + // + //volatile double rcond_plus_one = rcond + 1.0; + // + //if (rcond_plus_one == 1.0 || xisnan (rcond)) + // { + // err = -2; + // + // if (sing_handler) + // sing_handler (rcond); + // else + // (*current_liboctave_error_handler) + // ("matrix singular to machine precision, rcond = %g", + // rcond); + // } + //else + // REST OF CODE, EXCEPT rcond=1 + + rcond = 1.; + retval = b; + double *result = retval.fortran_vec (); + + int b_nc = b.cols (); + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, b_nc, tmp_data, + ldm, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + } + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrf"); + else + { + // Throw-away extra info LAPACK gives so as to not + // change output. + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = '1'; + + // Unfortunately, the time to calculate the condition + // number is dominant for narrow banded matrices and + // so we rely on the "err" flag from xPBTRF to flag + // singularity. The commented code below is left here + // for reference + + //F77_XFCN (dgbcon, DGBCON, + // (F77_CONST_CHAR_ARG2 (&job, 1), + // nc, n_lower, n_upper, tmp_data, ldm, pipvt, + // anorm, rcond, pz, piz, err + // F77_CHAR_ARG_LEN (1))); + // + //if (f77_exception_encountered) + // (*current_liboctave_error_handler) + // ("unrecoverable error in dgbcon"); + // + // if (err != 0) + // err = -2; + // + //volatile double rcond_plus_one = rcond + 1.0; + // + //if (rcond_plus_one == 1.0 || xisnan (rcond)) + // { + // err = -2; + // + // if (sing_handler) + // sing_handler (rcond); + // else + // (*current_liboctave_error_handler) + // ("matrix singular to machine precision, rcond = %g", + // rcond); + // } + //else + // REST OF CODE, EXCEPT rcond=1 + + rcond = 1.; + retval = b; + double *result = retval.fortran_vec (); + + int b_nc = b.cols (); + + job = 'N'; + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, b_nc, tmp_data, + ldm, pipvt, result, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::bsolve (SparseType &mattype, const SparseMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + for (int i = 0; i < b_nr; i++) + { + double tmp = Bx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (double, work, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + work[i] = 0.; + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + work[b.ridx(i)] = b.data(i); + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, work, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (work[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = work[i]; + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseMatrix::bsolve (SparseType &mattype, const ComplexMatrix& b, int& err, + double& rcond, solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + retval.resize (b_nr, b_nc); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bz, b.rows(), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + for (int i = 0; i < b_nr; i++) + retval (i, j) = Complex (Bx[i], Bz[i]); + } + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + int b_nc = b.cols (); + retval.resize (nr,b_nc); + + OCTAVE_LOCAL_BUFFER (double, Bz, nr); + OCTAVE_LOCAL_BUFFER (double, Bx, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + { + Complex c = b (i, j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bz, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + for (int i = 0; i < nr; i++) + retval (i, j) = Complex (Bx[i], Bz[i]); + } + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::bsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + volatile int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Banded_Hermitian) + { + int n_lower = mattype.nlower (); + int ldm = n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + { + int ri = ridx (i); + if (ri >= j) + m_band(ri - j, j) = data(i); + } + + char job = 'L'; + F77_XFCN (dpbtrf, DPBTRF, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, tmp_data, ldm, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + // Matrix is not positive definite!! Fall through to + // unsymmetric banded solver. + mattype.mark_as_unsymmetric (); + typ = SparseType::Banded; + + err = 0; + } + else + { + rcond = 1.; + int b_nr = b.rows (); + int b_nc = b.cols (); + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + volatile int x_nz = b.nnz (); + volatile int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (volatile int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bx, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + err = -1; + break; + } + + F77_XFCN (dpbtrs, DPBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, 1, tmp_data, + ldm, Bz, b_nr, err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dpbtrs"); + err = -1; + break; + } + + if (err != 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + err = -1; + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = + Complex (Bx[i], Bz[i]); + } + + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + + if (typ == SparseType::Banded) + { + // Create the storage for the banded form of the sparse matrix + int n_upper = mattype.nupper (); + int n_lower = mattype.nlower (); + int ldm = n_upper + 2 * n_lower + 1; + + Matrix m_band (ldm, nc); + double *tmp_data = m_band.fortran_vec (); + + if (! mattype.is_dense ()) + { + int ii = 0; + + for (int j = 0; j < ldm; j++) + for (int i = 0; i < nc; i++) + tmp_data[ii++] = 0.; + } + + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + m_band(ridx(i) - j + n_lower + n_upper, j) = data(i); + + Array ipvt (nr); + int *pipvt = ipvt.fortran_vec (); + + F77_XFCN (dgbtrf, DGBTRF, (nr, nr, n_lower, n_upper, tmp_data, + ldm, pipvt, err)); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrf"); + else + { + rcond = 0.0; + if (err != 0) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("matrix singular to machine precision"); + + } + else + { + char job = 'N'; + volatile int x_nz = b.nnz (); + int b_nc = b.cols (); + retval = SparseComplexMatrix (nr, b_nc, x_nz); + retval.xcidx(0) = 0; + volatile int ii = 0; + + OCTAVE_LOCAL_BUFFER (double, Bx, nr); + OCTAVE_LOCAL_BUFFER (double, Bz, nr); + + for (volatile int j = 0; j < b_nc; j++) + { + for (int i = 0; i < nr; i++) + { + Bx[i] = 0.; + Bz[i] = 0.; + } + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + Complex c = b.data(i); + Bx[b.ridx(i)] = ::real (c); + Bz[b.ridx(i)] = ::imag (c); + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bx, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + F77_XFCN (dgbtrs, DGBTRS, + (F77_CONST_CHAR_ARG2 (&job, 1), + nr, n_lower, n_upper, 1, tmp_data, + ldm, pipvt, Bz, b.rows (), err + F77_CHAR_ARG_LEN (1))); + + if (f77_exception_encountered) + { + (*current_liboctave_error_handler) + ("unrecoverable error in dgbtrs"); + break; + } + + // Count non-zeros in work vector and adjust + // space in retval if needed + int new_nnz = 0; + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + new_nnz++; + + if (ii + new_nnz > x_nz) + { + // Resize the sparse matrix + int sz = new_nnz * (b_nc - j) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + + for (int i = 0; i < nr; i++) + if (Bx[i] != 0. || Bz[i] != 0.) + { + retval.xridx(ii) = i; + retval.xdata(ii++) = + Complex (Bx[i], Bz[i]); + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + } + } + } + else if (typ != SparseType::Banded_Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +void * +SparseMatrix::factorize (int& err, double &rcond, Matrix &Control, Matrix &Info, + solve_singularity_handler sing_handler) const +{ + // The return values + void *Numeric; + err = 0; + + // Setup the control parameters + Control = Matrix (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + umfpack_di_report_control (control); + + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + int nr = rows (); + int nc = cols (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Info = Matrix (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, NULL, + &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve symbolic factorization failed"); + err = -1; + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + +#ifdef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + umfpack_di_report_numeric (Numeric, control); + + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } + else +#endif + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + err = -1; + } + else + { + umfpack_di_report_numeric (Numeric, control); + } + } + + if (err != 0) + umfpack_di_free_numeric (&Numeric); + + return Numeric; +} + +Matrix +SparseMatrix::fsolve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = + factorize (err, rcond, Control, Info, sing_handler); + + if (err == 0) + { + const double *Bx = b.fortran_vec (); + retval.resize (b.rows (), b.cols()); + double *result = retval.fortran_vec (); + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + + for (int j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr) + { + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, + &result[iidx], &Bx[iidx], + Numeric, control, info); + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + umfpack_di_report_status (control, status); + + err = -1; + + break; + } + } + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseMatrix +SparseMatrix::fsolve (SparseType &mattype, const SparseMatrix& b, int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + int x_nz = b.nnz (); + int ii = 0; + retval = SparseMatrix (b_nr, b_nc, x_nz); + + retval.xcidx(0) = 0; + for (int j = 0; j < b_nc; j++) + { + + for (int i = 0; i < b_nr; i++) + Bx[i] = b.elem (i, j); + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, Xx, + Bx, Numeric, control, + info); + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + umfpack_di_report_status (control, status); + + err = -1; + + break; + } + + for (int i = 0; i < b_nr; i++) + { + double tmp = Xx[i]; + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +ComplexMatrix +SparseMatrix::fsolve (SparseType &mattype, const ComplexMatrix& b, int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + retval.resize (b_nr, b_nc); + + OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Xz, b_nr); + + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, + Xx, Bx, Numeric, control, + info); + int status2 = umfpack_di_solve (UMFPACK_A, Ap, Ai, + Ax, Xz, Bz, Numeric, + control, info) ; + + if (status < 0 || status2 < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + umfpack_di_report_status (control, status); + + err = -1; + + break; + } + + for (int i = 0; i < b_nr; i++) + retval (i, j) = Complex (Xx[i], Xz[i]); + } + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +SparseComplexMatrix +SparseMatrix::fsolve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseComplexMatrix retval; + + int nr = rows (); + int nc = cols (); + err = 0; + + if (nr == 0 || nc == 0 || nr != nc || nr != b.rows ()) + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + else + { + // Print spparms("spumoni") info if requested + int typ = mattype.type (); + mattype.info (); + + if (typ == SparseType::Hermitian) + { + // XXX FIXME XXX Write the cholesky solver and only fall + // through if cholesky factorization fails + + (*current_liboctave_warning_handler) + ("SparseMatrix::solve XXX FIXME XXX Cholesky code not done"); + + mattype.mark_as_unsymmetric (); + typ = SparseType::Full; + } + + if (typ == SparseType::Full) + { + Matrix Control, Info; + void *Numeric = factorize (err, rcond, Control, Info, + sing_handler); + + if (err == 0) + { + int b_nr = b.rows (); + int b_nc = b.cols (); + int status = 0; + double *control = Control.fortran_vec (); + double *info = Info.fortran_vec (); + const int *Ap = cidx (); + const int *Ai = ridx (); + const double *Ax = data (); + + OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); + + // Take a first guess that the number of non-zero terms + // will be as many as in b + int x_nz = b.nnz (); + int ii = 0; + retval = SparseComplexMatrix (b_nr, b_nc, x_nz); + + OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); + OCTAVE_LOCAL_BUFFER (double, Xz, b_nr); + + retval.xcidx(0) = 0; + for (int j = 0; j < b_nc; j++) + { + for (int i = 0; i < b_nr; i++) + { + Complex c = b (i,j); + Bx[i] = ::real (c); + Bz[i] = ::imag (c); + } + + status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, Xx, + Bx, Numeric, control, + info); + int status2 = umfpack_di_solve (UMFPACK_A, Ap, Ai, + Ax, Xz, Bz, Numeric, + control, info) ; + + if (status < 0 || status2 < 0) + { + (*current_liboctave_error_handler) + ("SparseMatrix::solve solve failed"); + + umfpack_di_report_status (control, status); + + err = -1; + + break; + } + + for (int i = 0; i < b_nr; i++) + { + Complex tmp = Complex (Xx[i], Xz[i]); + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + int sz = x_nz * (b_nc - j) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + retval.change_capacity (sz); + x_nz = sz; + } + retval.xdata(ii) = tmp; + retval.xridx(ii++) = i; + } + } + retval.xcidx(j+1) = ii; + } + + retval.maybe_compress (); + +#ifndef HAVE_LSSOLVE + rcond = Info (UMFPACK_RCOND); + volatile double rcond_plus_one = rcond + 1.0; + + if (status == UMFPACK_WARNING_singular_matrix || + rcond_plus_one == 1.0 || xisnan (rcond)) + { + err = -2; + + if (sing_handler) + sing_handler (rcond); + else + (*current_liboctave_error_handler) + ("SparseMatrix::solve matrix singular to machine precision, rcond = %g", + rcond); + + } +#endif + + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + } + else if (typ != SparseType::Hermitian) + (*current_liboctave_error_handler) ("incorrect matrix type"); + } + + return retval; +} + +Matrix +SparseMatrix::solve (SparseType &mattype, const Matrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (SparseType &mattype, const Matrix& b, int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (SparseType &mattype, const Matrix& b, int& info, + double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (SparseType &mattype, const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return Matrix (); + } +} + +SparseMatrix +SparseMatrix::solve (SparseType &mattype, const SparseMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (SparseType &mattype, const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return SparseMatrix (); + } +} + +ComplexMatrix +SparseMatrix::solve (SparseType &mattype, const ComplexMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexMatrix +SparseMatrix::solve (SparseType &mattype, const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return ComplexMatrix (); + } +} + +SparseComplexMatrix +SparseMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (SparseType &mattype, const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + int typ = mattype.type (); + + if (typ == SparseType::Unknown) + typ = mattype.type (*this); + + if (typ == SparseType::Diagonal || typ == SparseType::Permuted_Diagonal) + return dsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Upper || typ == SparseType::Permuted_Upper) + return utsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Lower || typ == SparseType::Permuted_Lower) + return ltsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Banded || typ == SparseType::Banded_Hermitian) + return bsolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Tridiagonal || + typ == SparseType::Tridiagonal_Hermitian) + return trisolve (mattype, b, err, rcond, sing_handler); + else if (typ == SparseType::Full || typ == SparseType::Hermitian) + return fsolve (mattype, b, err, rcond, sing_handler); + else + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return SparseComplexMatrix (); + } +} + +ColumnVector +SparseMatrix::solve (SparseType &mattype, const ColumnVector& b) const +{ + int info; double rcond; + return solve (mattype, b, info, rcond); +} + +ColumnVector +SparseMatrix::solve (SparseType &mattype, const ColumnVector& b, int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond); +} + +ColumnVector +SparseMatrix::solve (SparseType &mattype, const ColumnVector& b, int& info, double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ColumnVector +SparseMatrix::solve (SparseType &mattype, const ColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix tmp (b); + return solve (mattype, tmp, info, rcond, sing_handler).column (0); +} + +ComplexColumnVector +SparseMatrix::solve (SparseType &mattype, const ComplexColumnVector& b) const +{ + int info; + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, int& info) const +{ + double rcond; + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, int& info, + double& rcond) const +{ + return solve (mattype, b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (SparseType &mattype, const ComplexColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix tmp (b); + return solve (mattype, tmp, info, rcond, sing_handler).column (0); +} + +Matrix +SparseMatrix::solve (const Matrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (const Matrix& b, int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (const Matrix& b, int& info, + double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +Matrix +SparseMatrix::solve (const Matrix& b, int& err, + double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +SparseMatrix +SparseMatrix::solve (const SparseMatrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (const SparseMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (const SparseMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +SparseMatrix +SparseMatrix::solve (const SparseMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +ComplexMatrix +SparseMatrix::solve (const ComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseMatrix::solve (const ComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexMatrix +SparseMatrix::solve (const ComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +SparseComplexMatrix +SparseMatrix::solve (const SparseComplexMatrix& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (const SparseComplexMatrix& b, + int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (const SparseComplexMatrix& b, + int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +SparseComplexMatrix +SparseMatrix::solve (const SparseComplexMatrix& b, + int& err, double& rcond, + solve_singularity_handler sing_handler) const +{ + SparseType mattype (*this); + return solve (mattype, b, err, rcond, sing_handler); +} + +ColumnVector +SparseMatrix::solve (const ColumnVector& b) const +{ + int info; double rcond; + return solve (b, info, rcond); +} + +ColumnVector +SparseMatrix::solve (const ColumnVector& b, int& info) const +{ + double rcond; + return solve (b, info, rcond); +} + +ColumnVector +SparseMatrix::solve (const ColumnVector& b, int& info, double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ColumnVector +SparseMatrix::solve (const ColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + Matrix tmp (b); + return solve (tmp, info, rcond, sing_handler).column (0); +} + +ComplexColumnVector +SparseMatrix::solve (const ComplexColumnVector& b) const +{ + int info; + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (const ComplexColumnVector& b, int& info) const +{ + double rcond; + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (const ComplexColumnVector& b, int& info, + double& rcond) const +{ + return solve (b, info, rcond, 0); +} + +ComplexColumnVector +SparseMatrix::solve (const ComplexColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const +{ + ComplexMatrix tmp (b); + return solve (tmp, info, rcond, sing_handler).column (0); +} + +Matrix +SparseMatrix::lssolve (const Matrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +Matrix +SparseMatrix::lssolve (const Matrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +Matrix +SparseMatrix::lssolve (const Matrix& b, int& info, int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseMatrix::lssolve not implemented yet"); + return Matrix (); +} + +SparseMatrix +SparseMatrix::lssolve (const SparseMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +SparseMatrix +SparseMatrix::lssolve (const SparseMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +SparseMatrix +SparseMatrix::lssolve (const SparseMatrix& b, int& info, int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseMatrix::lssolve not implemented yet"); + return SparseMatrix (); +} + +ComplexMatrix +SparseMatrix::lssolve (const ComplexMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseMatrix::lssolve (const ComplexMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexMatrix +SparseMatrix::lssolve (const ComplexMatrix& b, int& info, int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseMatrix::lssolve not implemented yet"); + return ComplexMatrix (); +} + +SparseComplexMatrix +SparseMatrix::lssolve (const SparseComplexMatrix& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseMatrix::lssolve (const SparseComplexMatrix& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +SparseComplexMatrix +SparseMatrix::lssolve (const SparseComplexMatrix& b, int& info, + int& rank) const +{ + info = -1; + (*current_liboctave_error_handler) + ("SparseMatrix::lssolve not implemented yet"); + return SparseComplexMatrix (); +} + +ColumnVector +SparseMatrix::lssolve (const ColumnVector& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ColumnVector +SparseMatrix::lssolve (const ColumnVector& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ColumnVector +SparseMatrix::lssolve (const ColumnVector& b, int& info, int& rank) const +{ + Matrix tmp (b); + return lssolve (tmp, info, rank).column (0); +} + +ComplexColumnVector +SparseMatrix::lssolve (const ComplexColumnVector& b) const +{ + int info; + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseMatrix::lssolve (const ComplexColumnVector& b, int& info) const +{ + int rank; + return lssolve (b, info, rank); +} + +ComplexColumnVector +SparseMatrix::lssolve (const ComplexColumnVector& b, int& info, + int& rank) const +{ + ComplexMatrix tmp (b); + return lssolve (tmp, info, rank).column (0); +} + +// other operations. + +SparseMatrix +SparseMatrix::map (d_d_Mapper f) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + bool f_zero = (f(0.0) == 0.0); + + // Count number of non-zero elements + int nel = (f_zero ? 0 : nr*nc - nz); + for (int i = 0; i < nz; i++) + if (f (data(i)) != 0.0) + nel++; + + SparseMatrix retval (nr, nc, nel); + + if (f_zero) + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + double tmp = f (elem (i, j)); + if (tmp != 0.0) + { + retval.data(ii) = tmp; + retval.ridx(ii++) = i; + } + } + retval.cidx(j+1) = ii; + } + } + else + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + retval.data(ii) = f (elem(i)); + retval.ridx(ii++) = ridx(i); + } + retval.cidx(j+1) = ii; + } + } + + return retval; +} + +SparseBoolMatrix +SparseMatrix::map (b_d_Mapper f) const +{ + int nr = rows (); + int nc = cols (); + int nz = nnz (); + bool f_zero = f(0.0); + + // Count number of non-zero elements + int nel = (f_zero ? 0 : nr*nc - nz); + for (int i = 0; i < nz; i++) + if (f (data(i)) != 0.0) + nel++; + + SparseBoolMatrix retval (nr, nc, nel); + + if (f_zero) + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + bool tmp = f (elem (i, j)); + if (tmp) + { + retval.data(ii) = tmp; + retval.ridx(ii++) = i; + } + } + retval.cidx(j+1) = ii; + } + } + else + { + int ii = 0; + for (int j = 0; j < nc; j++) + { + for (int i = cidx(j); i < cidx(j+1); i++) + { + retval.data(ii) = f (elem(i)); + retval.ridx(ii++) = ridx(i); + } + retval.cidx(j+1) = ii; + } + } + + return retval; +} + +SparseMatrix& +SparseMatrix::apply (d_d_Mapper f) +{ + *this = map (f); + return *this; +} + +bool +SparseMatrix::any_element_is_negative (bool neg_zero) const +{ + int nel = nnz (); + + if (neg_zero) + { + for (int i = 0; i < nel; i++) + if (lo_ieee_signbit (data (i))) + return true; + } + else + { + for (int i = 0; i < nel; i++) + if (data (i) < 0) + return true; + } + + return false; +} + +bool +SparseMatrix::any_element_is_inf_or_nan (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + double val = data (i); + if (xisinf (val) || xisnan (val)) + return true; + } + + return false; +} + +bool +SparseMatrix::all_elements_are_int_or_inf_or_nan (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + double val = data (i); + if (xisnan (val) || D_NINT (val) == val) + continue; + else + return false; + } + + return true; +} + +// Return nonzero if any element of M is not an integer. Also extract +// the largest and smallest values and return them in MAX_VAL and MIN_VAL. + +bool +SparseMatrix::all_integers (double& max_val, double& min_val) const +{ + int nel = nnz (); + + if (nel == 0) + return false; + + max_val = data (0); + min_val = data (0); + + for (int i = 0; i < nel; i++) + { + double val = data (i); + + if (val > max_val) + max_val = val; + + if (val < min_val) + min_val = val; + + if (D_NINT (val) != val) + return false; + } + + return true; +} + +bool +SparseMatrix::too_large_for_float (void) const +{ + int nel = nnz (); + + for (int i = 0; i < nel; i++) + { + double val = data (i); + + if (val > FLT_MAX || val < FLT_MIN) + return true; + } + + return false; +} + +SparseBoolMatrix +SparseMatrix::operator ! (void) const +{ + int nr = rows (); + int nc = cols (); + int nz1 = nnz (); + int nz2 = nr*nc - nz1; + + SparseBoolMatrix r (nr, nc, nz2); + + int ii = 0; + int jj = 0; + r.cidx (0) = 0; + for (int i = 0; i < nc; i++) + { + for (int j = 0; j < nr; j++) + { + if (jj < cidx(i+1) && ridx(jj) == j) + jj++; + else + { + r.data(ii) = true; + r.ridx(ii++) = j; + } + } + r.cidx (i+1) = ii; + } + + return r; +} + +// XXX FIXME XXX Do these really belong here? Maybe they should be +// in a base class? + +SparseBoolMatrix +SparseMatrix::all (int dim) const +{ + SPARSE_ALL_OP (dim); +} + +SparseBoolMatrix +SparseMatrix::any (int dim) const +{ + SPARSE_ANY_OP (dim); +} + +SparseMatrix +SparseMatrix::cumprod (int dim) const +{ + SPARSE_CUMPROD (SparseMatrix, double, cumprod); +} + +SparseMatrix +SparseMatrix::cumsum (int dim) const +{ + SPARSE_CUMSUM (SparseMatrix, double, cumsum); +} + +SparseMatrix +SparseMatrix::prod (int dim) const +{ + SPARSE_REDUCTION_OP (SparseMatrix, double, *=, 1.0, 1.0); +} + +SparseMatrix +SparseMatrix::sum (int dim) const +{ + SPARSE_REDUCTION_OP (SparseMatrix, double, +=, 0.0, 0.0); +} + +SparseMatrix +SparseMatrix::sumsq (int dim) const +{ +#define ROW_EXPR \ + double d = elem (i, j); \ + tmp[i] += d * d + +#define COL_EXPR \ + double d = elem (i, j); \ + tmp[j] += d * d + + SPARSE_BASE_REDUCTION_OP (SparseMatrix, double, ROW_EXPR, COL_EXPR, + 0.0, 0.0); + +#undef ROW_EXPR +#undef COL_EXPR +} + +SparseMatrix +SparseMatrix::abs (void) const +{ + int nz = nnz (); + + SparseMatrix retval (*this); + + for (int i = 0; i < nz; i++) + retval.data(i) = fabs(retval.data(i)); + + return retval; +} + +SparseMatrix +SparseMatrix::diag (int k) const +{ + int nnr = rows (); + int nnc = cols (); + + if (k > 0) + nnc -= k; + else if (k < 0) + nnr += k; + + SparseMatrix d; + + if (nnr > 0 && nnc > 0) + { + int ndiag = (nnr < nnc) ? nnr : nnc; + + // Count the number of non-zero elements + int nel = 0; + if (k > 0) + { + for (int i = 0; i < ndiag; i++) + if (elem (i, i+k) != 0.) + nel++; + } + else if ( k < 0) + { + for (int i = 0; i < ndiag; i++) + if (elem (i-k, i) != 0.) + nel++; + } + else + { + for (int i = 0; i < ndiag; i++) + if (elem (i, i) != 0.) + nel++; + } + + d = SparseMatrix (ndiag, 1, nel); + d.xcidx (0) = 0; + d.xcidx (1) = nel; + + int ii = 0; + if (k > 0) + { + for (int i = 0; i < ndiag; i++) + { + double tmp = elem (i, i+k); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else if ( k < 0) + { + for (int i = 0; i < ndiag; i++) + { + double tmp = elem (i-k, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + else + { + for (int i = 0; i < ndiag; i++) + { + double tmp = elem (i, i); + if (tmp != 0.) + { + d.xdata (ii) = tmp; + d.xridx (ii++) = i; + } + } + } + } + else + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); + + return d; +} + +Matrix +SparseMatrix::matrix_value (void) const +{ + int nr = rows (); + int nc = cols (); + + Matrix retval (nr, nc, 0.0); + for (int j = 0; j < nc; j++) + for (int i = cidx(j); i < cidx(j+1); i++) + retval.elem (ridx(i), j) = data (i); + + return retval; +} + +std::ostream& +operator << (std::ostream& os, const SparseMatrix& a) +{ + int nc = a.cols (); + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int j = 0; j < nc; j++) { + OCTAVE_QUIT; + for (int i = a.cidx(j); i < a.cidx(j+1); i++) { + os << a.ridx(i) + 1 << " " << j + 1 << " "; + octave_write_double (os, a.data(i)); + os << "\n"; + } + } + + return os; +} + +std::istream& +operator >> (std::istream& is, SparseMatrix& a) +{ + int nr = a.rows (); + int nc = a.cols (); + int nz = a.nnz (); + + if (nr < 1 || nc < 1) + is.clear (std::ios::badbit); + else + { + int itmp, jtmp, jold = 0; + double tmp; + int ii = 0; + + a.cidx (0) = 0; + for (int i = 0; i < nz; i++) + { + is >> itmp; + itmp--; + is >> jtmp; + jtmp--; + tmp = octave_read_double (is); + + if (is) + { + if (jold != jtmp) + { + for (int j = jold; j < jtmp; j++) + a.cidx(j+1) = ii; + + jold = jtmp; + } + a.data (ii) = tmp; + a.ridx (ii++) = itmp; + } + else + goto done; + } + + for (int j = jold; j < nc; j++) + a.cidx(j+1) = ii; + } + + done: + + return is; +} + +SparseMatrix +SparseMatrix::squeeze (void) const +{ + return MSparse::squeeze (); +} + +SparseMatrix +SparseMatrix::index (idx_vector& i, int resize_ok) const +{ + return MSparse::index (i, resize_ok); +} + +SparseMatrix +SparseMatrix::index (idx_vector& i, idx_vector& j, int resize_ok) const +{ + return MSparse::index (i, j, resize_ok); +} + +SparseMatrix +SparseMatrix::index (Array& ra_idx, int resize_ok) const +{ + return MSparse::index (ra_idx, resize_ok); +} + +SparseMatrix +SparseMatrix::reshape (const dim_vector& new_dims) const +{ + return MSparse::reshape (new_dims); +} + +SparseMatrix +SparseMatrix::permute (const Array& vec, bool inv) const +{ + return MSparse::permute (vec, inv); +} + +SparseMatrix +SparseMatrix::ipermute (const Array& vec) const +{ + return MSparse::ipermute (vec); +} + +// matrix by matrix -> matrix operations + +SparseMatrix +operator * (const SparseMatrix& m, const SparseMatrix& a) +{ +#ifdef HAVE_SPARSE_BLAS + // XXX FIXME XXX Isn't there a sparse BLAS ?? +#else + // Use Andy's sparse matrix multiply function + SPARSE_SPARSE_MUL (SparseMatrix, double); +#endif +} + +// XXX FIXME XXX -- it would be nice to share code among the min/max +// functions below. + +#define EMPTY_RETURN_CHECK(T) \ + if (nr == 0 || nc == 0) \ + return T (nr, nc); + +SparseMatrix +min (double d, const SparseMatrix& m) +{ + SparseMatrix result; + + int nr = m.rows (); + int nc = m.columns (); + + EMPTY_RETURN_CHECK (SparseMatrix); + + // Count the number of non-zero elements + if (d < 0.) + { + result = SparseMatrix (nr, nc, d); + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + double tmp = xmin (d, m.data (i)); + if (tmp != 0.) + { + int idx = m.ridx(i) + j * nr; + result.xdata(idx) = tmp; + result.xridx(idx) = m.ridx(i); + } + } + } + else + { + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + if (xmin (d, m.data (i)) != 0.) + nel++; + + result = SparseMatrix (nr, nc, nel); + + int ii = 0; + result.xcidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + double tmp = xmin (d, m.data (i)); + + if (tmp != 0.) + { + result.xdata(ii) = tmp; + result.xridx(ii++) = m.ridx(i); + } + } + result.xcidx(j+1) = ii; + } + } + + return result; +} + +SparseMatrix +min (const SparseMatrix& m, double d) +{ + return min (d, m); +} + +SparseMatrix +min (const SparseMatrix& a, const SparseMatrix& b) +{ + SparseMatrix r; + + if ((a.rows() == b.rows()) && (a.cols() == b.cols())) + { + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + else + { + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + r.cidx (0) = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + double tmp = xmin (a.data(ja), 0.); + if (tmp != 0.) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = tmp; + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + double tmp = xmin (0., b.data(jb)); + if (tmp != 0.) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = tmp; + jx++; + } + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmin (a.data(ja), b.data(jb)); + if (tmp != 0.) + { + r.data(jx) = tmp; + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + r.maybe_compress (); + } + } + else + (*current_liboctave_error_handler) ("matrix size mismatch"); + + return r; +} + +SparseMatrix +max (double d, const SparseMatrix& m) +{ + SparseMatrix result; + + int nr = m.rows (); + int nc = m.columns (); + + EMPTY_RETURN_CHECK (SparseMatrix); + + // Count the number of non-zero elements + if (d > 0.) + { + result = SparseMatrix (nr, nc, d); + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + double tmp = xmax (d, m.data (i)); + + if (tmp != 0.) + { + int idx = m.ridx(i) + j * nr; + result.xdata(idx) = tmp; + result.xridx(idx) = m.ridx(i); + } + } + } + else + { + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + if (xmax (d, m.data (i)) != 0.) + nel++; + + result = SparseMatrix (nr, nc, nel); + + int ii = 0; + result.xcidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + double tmp = xmax (d, m.data (i)); + if (tmp != 0.) + { + result.xdata(ii) = tmp; + result.xridx(ii++) = m.ridx(i); + } + } + result.xcidx(j+1) = ii; + } + } + + return result; +} + +SparseMatrix +max (const SparseMatrix& m, double d) +{ + return max (d, m); +} + +SparseMatrix +max (const SparseMatrix& a, const SparseMatrix& b) +{ + SparseMatrix r; + + if ((a.rows() == b.rows()) && (a.cols() == b.cols())) + { + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a_nr != b_nr || a_nc != b_nc) + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + else + { + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + int jx = 0; + r.cidx (0) = 0; + for (int i = 0 ; i < a_nc ; i++) + { + int ja = a.cidx(i); + int ja_max = a.cidx(i+1); + bool ja_lt_max= ja < ja_max; + + int jb = b.cidx(i); + int jb_max = b.cidx(i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max ) + { + OCTAVE_QUIT; + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx(ja) < b.ridx(jb)))) + { + double tmp = xmax (a.data(ja), 0.); + if (tmp != 0.) + { + r.ridx(jx) = a.ridx(ja); + r.data(jx) = tmp; + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + } + else if (( !ja_lt_max ) || + (jb_lt_max && (b.ridx(jb) < a.ridx(ja)) ) ) + { + double tmp = xmax (0., b.data(jb)); + if (tmp != 0.) + { + r.ridx(jx) = b.ridx(jb); + r.data(jx) = tmp; + jx++; + } + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmax (a.data(ja), b.data(jb)); + if (tmp != 0.) + { + r.data(jx) = tmp; + r.ridx(jx) = a.ridx(ja); + jx++; + } + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx(i+1) = jx; + } + + r.maybe_compress (); + } + } + else + (*current_liboctave_error_handler) ("matrix size mismatch"); + + return r; +} + +SPARSE_SMS_CMP_OPS (SparseMatrix, 0.0, , double, 0.0, ) +SPARSE_SMS_BOOL_OPS (SparseMatrix, double, 0.0) + +SPARSE_SSM_CMP_OPS (double, 0.0, , SparseMatrix, 0.0, ) +SPARSE_SSM_BOOL_OPS (double, SparseMatrix, 0.0) + +SPARSE_SMSM_CMP_OPS (SparseMatrix, 0.0, , SparseMatrix, 0.0, ) +SPARSE_SMSM_BOOL_OPS (SparseMatrix, SparseMatrix, 0.0) + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/dSparse.h b/liboctave/dSparse.h new file mode 100644 --- /dev/null +++ b/liboctave/dSparse.h @@ -0,0 +1,412 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_dSparse_h) +#define octave_dSparse_h 1 + +#include "dMatrix.h" +#include "dNDArray.h" +#include "CMatrix.h" +#include "dColVector.h" +#include "CColVector.h" + +#include "dbleDET.h" +#include "MSparse.h" +#include "MSparse-defs.h" +#include "Sparse-op-defs.h" +#include "SparseType.h" + +class SparseComplexMatrix; +class SparseBoolMatrix; + +class +SparseMatrix : public MSparse +{ + public: + + typedef void (*solve_singularity_handler) (double rcond); + + SparseMatrix (void) : MSparse () { } + + SparseMatrix (int r, int c) : MSparse (r, c) { } + + explicit SparseMatrix (int r, int c, double val) + : MSparse (r, c, val) { } + + SparseMatrix (const SparseMatrix& a) : MSparse (a) { } + + SparseMatrix (const SparseMatrix& a, const dim_vector& dv) + : MSparse (a, dv) { } + + SparseMatrix (const MSparse& a) : MSparse (a) { } + + explicit SparseMatrix (const SparseBoolMatrix& a); + + explicit SparseMatrix (const Matrix& a) : MSparse (a) { } + + explicit SparseMatrix (const NDArray& a) : MSparse (a) { } + + explicit SparseMatrix (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : MSparse (a, r, c, nr, nc, sum_terms) { } + + explicit SparseMatrix (const Array a, const Array& r, + const Array& c, int nr = -1, + int nc = -1, bool sum_terms = true) + : MSparse (a, r, c, nr, nc, sum_terms) { } + + SparseMatrix (int r, int c, int num_nz) : MSparse (r, c, num_nz) { } + + SparseMatrix& operator = (const SparseMatrix& a) + { + MSparse::operator = (a); + return *this; + } + + bool operator == (const SparseMatrix& a) const; + bool operator != (const SparseMatrix& a) const; + + bool is_symmetric (void) const; + + SparseMatrix max (int dim = 0) const; + SparseMatrix max (Array2& index, int dim = 0) const; + SparseMatrix min (int dim = 0) const; + SparseMatrix min (Array2& index, int dim = 0) const; + + // destructive insert/delete/reorder operations + + SparseMatrix& insert (const SparseMatrix& a, int r, int c); + + SparseMatrix concat (const SparseMatrix& rb, const Array& ra_idx); + SparseComplexMatrix concat (const SparseComplexMatrix& rb, + const Array& ra_idx); + + friend SparseMatrix real (const SparseComplexMatrix& a); + friend SparseMatrix imag (const SparseComplexMatrix& a); + + friend SparseMatrix atan2 (const double& x, const SparseMatrix& y); + friend SparseMatrix atan2 (const SparseMatrix& x, const double& y); + friend SparseMatrix atan2 (const SparseMatrix& x, const SparseMatrix& y); + + SparseMatrix transpose (void) const + { + return MSparse::transpose (); + } + + SparseMatrix inverse (void) const; + SparseMatrix inverse (int& info) const; + SparseMatrix inverse (int& info, double& rcond, int force = 0, + int calc_cond = 1) const; + + DET determinant (void) const; + DET determinant (int& info) const; + DET determinant (int& info, double& rcond, int calc_cond = 1) const; + +private: + // Diagonal matrix solvers + Matrix dsolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix dsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix dsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix dsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Upper triangular matrix solvers + Matrix utsolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix utsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix utsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix utsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Lower triangular matrix solvers + Matrix ltsolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix ltsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix ltsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix ltsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Tridiagonal matrix solvers + Matrix trisolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix trisolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix trisolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix trisolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Banded matrix solvers (umfpack/cholesky) + Matrix bsolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix bsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix bsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix bsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Full matrix solvers (umfpack/cholesky) + void * factorize (int& err, double &rcond, Matrix &Control, Matrix &Info, + solve_singularity_handler sing_handler) const; + + Matrix fsolve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix fsolve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix fsolve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix fsolve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + +public: + // Generic interface to solver with no probing of type + Matrix solve (SparseType &typ, const Matrix& b) const; + Matrix solve (SparseType &typ, const Matrix& b, int& info) const; + Matrix solve (SparseType &typ, const Matrix& b, int& info, + double& rcond) const; + Matrix solve (SparseType &typ, const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, + int& info) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond) const; + ComplexMatrix solve (SparseType &typ, const ComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseMatrix solve (SparseType &typ, const SparseMatrix& b) const; + SparseMatrix solve (SparseType &typ, const SparseMatrix& b, + int& info) const; + SparseMatrix solve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond) const; + SparseMatrix solve (SparseType &typ, const SparseMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (SparseType &typ, + const SparseComplexMatrix& b) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, + int& info) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, + int& info, double& rcond) const; + SparseComplexMatrix solve (SparseType &typ, const SparseComplexMatrix& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ColumnVector solve (SparseType &typ, const ColumnVector& b) const; + ColumnVector solve (SparseType &typ, const ColumnVector& b, + int& info) const; + ColumnVector solve (SparseType &typ, const ColumnVector& b, + int& info, double& rcond) const; + ColumnVector solve (SparseType &typ, const ColumnVector& b, int& info, + double& rcond, solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (SparseType &typ, + const ComplexColumnVector& b) const; + ComplexColumnVector solve (SparseType &typ, + const ComplexColumnVector& b, int& info) const; + ComplexColumnVector solve (SparseType &typ, const ComplexColumnVector& b, + int& info, double& rcond) const; + ComplexColumnVector solve (SparseType &typ, const ComplexColumnVector& b, + int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + // Generic interface to solver with probing of type + Matrix solve (const Matrix& b) const; + Matrix solve (const Matrix& b, int& info) const; + Matrix solve (const Matrix& b, int& info, double& rcond) const; + Matrix solve (const Matrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexMatrix solve (const ComplexMatrix& b) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info, + double& rcond) const; + ComplexMatrix solve (const ComplexMatrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + SparseMatrix solve (const SparseMatrix& b) const; + SparseMatrix solve (const SparseMatrix& b, int& info) const; + SparseMatrix solve (const SparseMatrix& b, int& info, + double& rcond) const; + SparseMatrix solve (const SparseMatrix& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + SparseComplexMatrix solve (const SparseComplexMatrix& b) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info, + double& rcond) const; + SparseComplexMatrix solve (const SparseComplexMatrix& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const; + + ColumnVector solve (const ColumnVector& b) const; + ColumnVector solve (const ColumnVector& b, int& info) const; + ColumnVector solve (const ColumnVector& b, int& info, double& rcond) const; + ColumnVector solve (const ColumnVector& b, int& info, double& rcond, + solve_singularity_handler sing_handler) const; + + ComplexColumnVector solve (const ComplexColumnVector& b) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info, + double& rcond) const; + ComplexColumnVector solve (const ComplexColumnVector& b, int& info, + double& rcond, + solve_singularity_handler sing_handler) const; + + // Minimum-norm solvers + Matrix lssolve (const Matrix& b) const; + Matrix lssolve (const Matrix& b, int& info) const; + Matrix lssolve (const Matrix& b, int& info, int& rank) const; + + ComplexMatrix lssolve (const ComplexMatrix& b) const; + ComplexMatrix lssolve (const ComplexMatrix& b, int& info) const; + ComplexMatrix lssolve (const ComplexMatrix& b, int& info, + int& rank) const; + + SparseMatrix lssolve (const SparseMatrix& b) const; + SparseMatrix lssolve (const SparseMatrix& b, int& info) const; + SparseMatrix lssolve (const SparseMatrix& b, int& info, int& rank) const; + + SparseComplexMatrix lssolve (const SparseComplexMatrix& b) const; + SparseComplexMatrix lssolve (const SparseComplexMatrix& b, + int& info) const; + SparseComplexMatrix lssolve (const SparseComplexMatrix& b, int& info, + int& rank) const; + + ColumnVector lssolve (const ColumnVector& b) const; + ColumnVector lssolve (const ColumnVector& b, int& info) const; + ColumnVector lssolve (const ColumnVector& b, int& info, int& rank) const; + + ComplexColumnVector lssolve (const ComplexColumnVector& b) const; + ComplexColumnVector lssolve (const ComplexColumnVector& b, int& info) const; + ComplexColumnVector lssolve (const ComplexColumnVector& b, int& info, + int& rank) const; + + // other operations + SparseMatrix map (d_d_Mapper f) const; + SparseBoolMatrix map (b_d_Mapper f) const; + + SparseMatrix& apply (d_d_Mapper f); + + bool any_element_is_negative (bool = false) const; + bool any_element_is_inf_or_nan (void) const; + bool all_elements_are_int_or_inf_or_nan (void) const; + bool all_integers (double& max_val, double& min_val) const; + bool too_large_for_float (void) const; + + SparseBoolMatrix operator ! (void) const; + + SparseBoolMatrix all (int dim = -1) const; + SparseBoolMatrix any (int dim = -1) const; + + SparseMatrix cumprod (int dim = -1) const; + SparseMatrix cumsum (int dim = -1) const; + SparseMatrix prod (int dim = -1) const; + SparseMatrix sum (int dim = -1) const; + SparseMatrix sumsq (int dim = -1) const; + SparseMatrix abs (void) const; + + SparseMatrix diag (int k = 0) const; + + Matrix matrix_value (void) const; + + SparseMatrix squeeze (void) const; + + SparseMatrix index (idx_vector& i, int resize_ok) const; + + SparseMatrix index (idx_vector& i, idx_vector& j, int resize_ok) const; + + SparseMatrix index (Array& ra_idx, int resize_ok) const; + + SparseMatrix reshape (const dim_vector& new_dims) const; + + SparseMatrix permute (const Array& vec, bool inv = false) const; + + SparseMatrix ipermute (const Array& vec) const; + + // i/o + + friend std::ostream& operator << (std::ostream& os, const SparseMatrix& a); + friend std::istream& operator >> (std::istream& is, SparseMatrix& a); +}; + +extern SparseMatrix operator * (const SparseMatrix& a, + const SparseMatrix& b); + +extern SparseMatrix min (double d, const SparseMatrix& m); +extern SparseMatrix min (const SparseMatrix& m, double d); +extern SparseMatrix min (const SparseMatrix& a, const SparseMatrix& b); + +extern SparseMatrix max (double d, const SparseMatrix& m); +extern SparseMatrix max (const SparseMatrix& m, double d); +extern SparseMatrix max (const SparseMatrix& a, const SparseMatrix& b); + +SPARSE_SMS_CMP_OP_DECLS (SparseMatrix, double) +SPARSE_SMS_BOOL_OP_DECLS (SparseMatrix, double) + +SPARSE_SSM_CMP_OP_DECLS (double, SparseMatrix) +SPARSE_SSM_BOOL_OP_DECLS (double, SparseMatrix) + +SPARSE_SMSM_CMP_OP_DECLS (SparseMatrix, SparseMatrix) +SPARSE_SMSM_BOOL_OP_DECLS (SparseMatrix, SparseMatrix) + +SPARSE_FORWARD_DEFS (MSparse, SparseMatrix, Matrix, double) + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/dbleDET.h b/liboctave/dbleDET.h --- a/liboctave/dbleDET.h +++ b/liboctave/dbleDET.h @@ -29,6 +29,7 @@ DET { friend class Matrix; +friend class SparseMatrix; public: diff --git a/liboctave/mx-base.h b/liboctave/mx-base.h --- a/liboctave/mx-base.h +++ b/liboctave/mx-base.h @@ -45,6 +45,12 @@ #include "dDiagMatrix.h" #include "CDiagMatrix.h" +// Sparse Matrix classes. + +#include "boolSparse.h" +#include "dSparse.h" +#include "CSparse.h" + // N-d Array classes. #include "boolNDArray.h" diff --git a/liboctave/oct-spparms.cc b/liboctave/oct-spparms.cc new file mode 100644 --- /dev/null +++ b/liboctave/oct-spparms.cc @@ -0,0 +1,122 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "config.h" +#include "lo-ieee.h" + +#include "oct-spparms.h" + +SparseParams Voctave_sparse_controls; + +void +SparseParams::defaults (void) +{ + Voctave_sparse_controls (0) = 0; // spumoni + Voctave_sparse_controls (1) = 1; // ths_rel + Voctave_sparse_controls (2) = 1; // ths_abs + Voctave_sparse_controls (3) = 0; // exact_d + Voctave_sparse_controls (4) = 3; // supernd + Voctave_sparse_controls (5) = 3; // rreduce + Voctave_sparse_controls (6) = 0.5; // wh_frac + Voctave_sparse_controls (7) = 1; // autommd + Voctave_sparse_controls (8) = 1; // autoamd + Voctave_sparse_controls (9) = 0.1; // piv_tol + Voctave_sparse_controls (10) = 0.5; // bandden + Voctave_sparse_controls (11) = 1; // umfpack +} + +void +SparseParams::tight (void) +{ + Voctave_sparse_controls (0) = 0; // spumoni + Voctave_sparse_controls (1) = 1; // ths_rel + Voctave_sparse_controls (2) = 0; // ths_abs + Voctave_sparse_controls (3) = 1; // exact_d + Voctave_sparse_controls (4) = 1; // supernd + Voctave_sparse_controls (5) = 1; // rreduce + Voctave_sparse_controls (6) = 0.5; // wh_frac + Voctave_sparse_controls (7) = 1; // autommd + Voctave_sparse_controls (8) = 1; // autoamd + Voctave_sparse_controls (9) = 0.1; // piv_tol + Voctave_sparse_controls (10) = 0.5; // bandden + Voctave_sparse_controls (11) = 1; // umfpack +} + +void +SparseParams::init_keys (void) +{ + keys (0) = "spumoni"; + keys (1) = "ths_rel"; + keys (2) = "ths_abs"; + keys (3) = "exact_d"; + keys (4) = "supernd"; + keys (5) = "rreduce"; + keys (6) = "wh_frac"; + keys (7) = "autommd"; + keys (8) = "autoamd"; + keys (9) = "piv_tol"; + keys (10) = "bandden"; + keys (11) = "umfpack"; +} + +SparseParams& +SparseParams::operator = (const SparseParams& a) +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + params (i) = a.params (i); + + return *this; +} + +bool +SparseParams::set_key (const std::string key, const double& val) +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + if (keys (i) == key) + { + params(i) = val; + return true; + } + return false; +} + +double +SparseParams::get_key (const std::string key) +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + if (keys (i) == key) + return params(i); + + return octave_NaN; +} + +void +SparseParams::print_info (std::ostream& os, const std::string& prefix) const +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + os << prefix << keys(i) << ": " << params(i) << "\n"; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/oct-spparms.h b/liboctave/oct-spparms.h new file mode 100644 --- /dev/null +++ b/liboctave/oct-spparms.h @@ -0,0 +1,78 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_oct_spparms_h) +#define octave_oct_spparms_h 1 + +#include +#include + +#include + +#include "str-vec.h" +#include "dColVector.h" + +#define OCTAVE_SPARSE_CONTROLS_SIZE 12 + +class +SparseParams +{ + public: + SparseParams (void) : params (ColumnVector (OCTAVE_SPARSE_CONTROLS_SIZE)), + keys (string_vector (OCTAVE_SPARSE_CONTROLS_SIZE)) + { defaults (); init_keys (); } + + void defaults (void); + + void tight (void); + + SparseParams& operator = (const SparseParams& a); + + double& operator () (int n) { return params (n); } + double operator () (int n) const { return params (n); } + + string_vector get_keys (void) const { return keys; } + + ColumnVector get_vals (void) const { return params; } + + bool set_key (const std::string key, const double& val); + + double get_key (const std::string key); + + void print_info (std::ostream& os, const std::string& prefix) const; + + private: + void init_keys (void); + + ColumnVector params; + + string_vector keys; +}; + +extern SparseParams Voctave_sparse_controls; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/sparse-base-lu.cc b/liboctave/sparse-base-lu.cc new file mode 100644 --- /dev/null +++ b/liboctave/sparse-base-lu.cc @@ -0,0 +1,70 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sparse-base-lu.h" + +template +p_type +sparse_base_lu :: Pr (void) const +{ + int nr = Lfact.rows (); + + p_type Pout (nr, nr, nr); + + for (int i = 0; i < nr; i++) + { + Pout.cidx (i) = i; + Pout.ridx (P (i)) = i; + Pout.data (i) = 1; + } + Pout.cidx (nr) = nr; + + return Pout; +} + +template +p_type +sparse_base_lu :: Pc (void) const +{ + int nc = Ufact.cols (); + + p_type Pout (nc, nc, nc); + + for (int i = 0; i < nc; i++) + { + Pout.cidx (i) = i; + Pout.ridx (i) = Q (i); + Pout.data (i) = 1; + } + Pout.cidx (nc) = nc; + + return Pout; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/sparse-base-lu.h b/liboctave/sparse-base-lu.h new file mode 100644 --- /dev/null +++ b/liboctave/sparse-base-lu.h @@ -0,0 +1,85 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + +#if !defined (octave_sparse_base_lu_h) +#define octave_sparse_base_lu_h 1 + +#include "MArray.h" + +template +class +sparse_base_lu +{ +public: + + sparse_base_lu (void) { } + + sparse_base_lu (const sparse_base_lu& a) + : Lfact (a.Lfact), Ufact (a.Ufact), cond (a.cond), P (a.P), Q (a.Q) { } + + sparse_base_lu& operator = (const sparse_base_lu& a) + { + if (this != &a) + { + Lfact = a.Lfact; + Ufact = a.Ufact; + cond = a.cond; + P = a.P; + Q = a.Q; + } + return *this; + } + + ~sparse_base_lu (void) { } + + lu_type L (void) const { return Lfact; } + + lu_type U (void) const { return Ufact; } + + p_type Pc (void) const; + + p_type Pr (void) const; + + MArray row_perm (void) const { return P; } + + MArray col_perm (void) const { return Q; } + + double rcond (void) const { return cond; } + +protected: + + lu_type Lfact; + lu_type Ufact; + + double cond; + + MArray P; + MArray Q; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/sparse-mk-ops.awk b/liboctave/sparse-mk-ops.awk new file mode 100644 --- /dev/null +++ b/liboctave/sparse-mk-ops.awk @@ -0,0 +1,239 @@ +BEGIN { + declare_types = 0; + generate_ops = 0; + ntypes = 0; +} { + if (NR == 1 && make_inclusive_header) + { + print "// DO NOT EDIT -- generated by sparse-mk-ops"; + tmp = make_inclusive_header; + gsub (/[\.-]/, "_", tmp); + printf ("#if !defined (octave_%s)\n", tmp); + printf ("#define octave_%s 1\n", tmp); + } +} +/^#/ { + if ($2 == "types") + declare_types = 1; + else if ($2 == "ops") + { + generate_ops = 1; + declare_types = 0; + } + next; +} { + if (declare_types) + { + ntypes++; + + if (NF == 6) + { + scalar_zero_val[ntypes] = $6; + fwd_decl_ok[ntypes] = $5 == "YES"; + header[ntypes] = $4 == "NONE" ? "" : $4; + class[ntypes] = $3; + type[ntypes] = $2; + tag[ntypes] = $1; + rev_tag[$1] = ntypes; + } + else + printf ("skipping line %d: %s\n", NR, $0); + } + else if (generate_ops) + { + if (NF >= 5) + { + result_tag_1 = $1; + result_tag_2 = $2; + lhs_tag = $3; + rhs_tag = $4; + op_type = $5; + + bin_ops = index (op_type, "B") != 0; + cmp_ops = index (op_type, "C") != 0; + eqne_ops = index (op_type, "E") != 0; + bool_ops = index (op_type, "L") != 0; + + n = 5; + + lhs_conv = cmp_ops ? $(++n) : ""; + rhs_conv = cmp_ops ? $(++n) : ""; + + if (lhs_conv == "NONE") + lhs_conv = ""; + + if (rhs_conv == "NONE") + rhs_conv = ""; + + k = 0 + while (NF > n) + bool_headers[k++] = $(++n); + + cc_file = sprintf ("%s-%s-%s.cc", prefix, lhs_tag, rhs_tag); + h_file = sprintf ("%s-%s-%s.h", prefix, lhs_tag, rhs_tag); + + if (list_cc_files) + { + print cc_file; + next; + } + + if (list_h_files) + { + print h_file; + next; + } + + if (make_inclusive_header) + { + printf ("#include \"%s\"\n", h_file); + next; + } + + h_guard = sprintf ("octave_%s_%s_%s_h", prefix, lhs_tag, rhs_tag); + + result_num_1 = rev_tag[result_tag_1]; + result_num_2 = rev_tag[result_tag_2]; + lhs_num = rev_tag[lhs_tag]; + rhs_num = rev_tag[rhs_tag]; + + result_type_1 = type[result_num_1]; + result_type_2 = type[result_num_2]; + lhs_type = type[lhs_num]; + rhs_type = type[rhs_num]; + + result_scalar_zero_val_1 = scalar_zero_val[result_num_1]; + result_scalar_zero_val_2 = scalar_zero_val[result_num_2]; + lhs_scalar_zero_val = scalar_zero_val[lhs_num]; + rhs_scalar_zero_val = scalar_zero_val[rhs_num]; + + result_header_1 = header[result_num_1]; + result_header_2 = header[result_num_2]; + lhs_header = header[lhs_num]; + rhs_header = header[rhs_num]; + + lhs_class = class[lhs_num]; + rhs_class = class[rhs_num]; + + print "// DO NOT EDIT -- generated by sparse-mk-ops" > h_file; + + printf ("#if !defined (%s)\n", h_guard) >> h_file; + printf ("#define %s 1\n", h_guard) >> h_file; + + if (result_header_1) + { + if (result_fwd_decl_ok) + printf ("class %s\n", result_type_1) >> h_file; + else + printf ("#include \"%s\"\n", result_header_1) >> h_file; + } + + if (result_header_2 && ! (result_header_2 == result_header_1)) + { + if (result_fwd_decl_ok) + printf ("class %s\n", result_type_2) >> h_file; + else + printf ("#include \"%s\"\n", result_header_2) >> h_file; + } + + if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2)) + { + if (result_fwd_decl_ok) + printf ("class %s\n", lhs_type) >> h_file; + else + printf ("#include \"%s\"\n", lhs_header) >> h_file; + } + + if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2)) + { + if (result_fwd_decl_ok) + printf ("class %s\n", rhs_type) >> h_file; + else + printf ("#include \"%s\"\n", rhs_header) >> h_file; + } + + printf ("#include \"Sparse-op-defs.h\"\n") >> h_file; + + if (bin_ops) + printf ("SPARSE_%s%s_BIN_OP_DECLS (%s, %s, %s, %s)\n", lhs_class, + rhs_class, result_type_1, result_type_2, lhs_type, + rhs_type) >> h_file + + if (cmp_ops) + printf ("SPARSE_%s%s_CMP_OP_DECLS (%s, %s)\n", lhs_class, + rhs_class, lhs_type, rhs_type) >> h_file + + if (eqne_ops) + printf ("SPARSE_%s%s_EQNE_OP_DECLS (%s, %s)\n", lhs_class, + rhs_class, lhs_type, rhs_type) >> h_file + + if (bool_ops) + printf ("SPARSE_%s%s_BOOL_OP_DECLS (%s, %s)\n", lhs_class, + rhs_class, lhs_type, rhs_type) >> h_file + + + print "#endif" >> h_file; + + close (h_file); + + + print "// DO NOT EDIT -- generated by sparse-mk-ops" > cc_file; + + ## print "#ifdef HAVE_CONFIG_H" >> cc_file; + print "#include " >> cc_file; + ## print "#endif" >> cc_file; + + print "#include \"Array-util.h\"" >> cc_file; + print "#include \"quit.h\"" >> cc_file; + + printf ("#include \"%s\"\n", h_file) >> cc_file; + + for (i in bool_headers) + { + printf ("#include \"%s\"\n", bool_headers[i]) >> cc_file; + delete bool_headers[i]; + } + + if (result_header_1) + printf ("#include \"%s\"\n", result_header_1) >> cc_file; + + if (result_header_2 && ! (result_header_2 == result_header_1)) + printf ("#include \"%s\"\n", result_header_2) >> cc_file; + + if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2)) + printf ("#include \"%s\"\n", lhs_header) >> cc_file; + + if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_heaer == result_header_2)) + printf ("#include \"%s\"\n", rhs_header) >> cc_file; + + if (bin_ops) + printf ("SPARSE_%s%s_BIN_OPS (%s, %s, %s, %s)\n", lhs_class, + rhs_class, result_type_1, result_type_2, lhs_type, + rhs_type) >> cc_file + + if (cmp_ops) + printf ("SPARSE_%s%s_CMP_OPS (%s, %s, %s, %s, %s, %s)\n", + lhs_class, rhs_class, lhs_type, lhs_scalar_zero_val, + lhs_conv, rhs_type, rhs_scalar_zero_val, rhs_conv) >> cc_file + + if (eqne_ops) + printf ("SPARSE_%s%s_EQNE_OPS (%s, %s, %s, %s, %s, %s)\n", + lhs_class, rhs_class, lhs_type, lhs_scalar_zero_val, + lhs_conv, rhs_type, rhs_scalar_zero_val, rhs_conv) >> cc_file + + if (bool_ops) + printf ("SPARSE_%s%s_BOOL_OPS2 (%s, %s, %s, %s)\n", lhs_class, + rhs_class, lhs_type, rhs_type, lhs_scalar_zero_val, + rhs_scalar_zero_val) >> cc_file + + + close (cc_file); + } + else + printf ("skipping line %d: %s\n", NR, $0); + } +} +END { + if (make_inclusive_header) + print "#endif"; +} diff --git a/liboctave/sparse-mx-ops b/liboctave/sparse-mx-ops new file mode 100644 --- /dev/null +++ b/liboctave/sparse-mx-ops @@ -0,0 +1,45 @@ +# types +# +# key typename object-type header fwd-decl-ok scalar-zero +# +# S: scalar +# M: matrix +# DM: diagonal matrix +# ND: N-d array +# SM: sparse matrix +# +sm SparseMatrix SM dSparse.h YES 0.0 +scm SparseComplexMatrix SM CSparse.h YES 0.0 +sbm SparseBoolMatrix SM boolSparse.h YES false +b bool S NONE NO false +bm boolMatrix M boolMatrix.h YES false +s double S NONE NO 0.0 +cs Complex S oct-cmplx.h NO 0.0 +m Matrix M dMatrix.h YES 0.0 +cm ComplexMatrix M CMatrix.h YES 0.0 +# ops +# result_t_1 result_t_2 lhs_t rhs_t op-type lhs_conv rhs_conv headers ... +# +# op-type is one of +# +# B: binary ops, + - * / +# C: comparison ops, < <= == != >= > +# E: == != (Only one of C or E can be used!!) +# L: logical ops, & | +# +cm scm sm cs BCL NONE real boolSparse.h +cm scm cs sm BCL real NONE boolSparse.h +cm scm scm s BCL real NONE boolSparse.h +cm scm s scm BCL NONE real boolSparse.h +scm scm scm sm BCL real NONE boolSparse.h +scm scm sm scm BCL NONE real boolSparse.h +m sm m sm BCL NONE NONE boolSparse.h +cm scm m scm BCL NONE real boolSparse.h +cm scm cm sm BCL real NONE boolSparse.h +cm scm cm scm BCL real real boolSparse.h +m sm sm m BCL NONE NONE boolSparse.h +cm scm scm m BCL real NONE boolSparse.h +cm scm sm cm BCL NONE real boolSparse.h +cm scm scm cm BCL real real boolSparse.h +bm sbm bm sbm EL +bm sbm sbm bm EL diff --git a/liboctave/sparse-sort.cc b/liboctave/sparse-sort.cc new file mode 100644 --- /dev/null +++ b/liboctave/sparse-sort.cc @@ -0,0 +1,56 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "oct-sort.cc" +#include "quit.h" + +#include "sparse-sort.h" + +// A simple class and instantiation of the octave merge sort class +// to sort sparse data before matrix creation. This is significantly +// faster than using octave_qsort. + +bool +octave_sparse_sidxl_comp (octave_sparse_sort_idxl* i, + octave_sparse_sort_idxl* j) +{ + int tmp = i->c - j->c; + if (tmp < 0) + return true; + else if (tmp > 0) + return false; + return (i->r < j->r); +} + +// Instantiate the sparse sorting class +template class octave_sort; + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/liboctave/sparse-sort.h b/liboctave/sparse-sort.h new file mode 100644 --- /dev/null +++ b/liboctave/sparse-sort.h @@ -0,0 +1,45 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_sort_h) +#define octave_sparse_sort_h + +#include "oct-sort.h" + +class +octave_sparse_sort_idxl +{ + public: + unsigned int r; + unsigned int c; + unsigned int idx; +}; + +bool octave_sparse_sidxl_comp (octave_sparse_sort_idxl* i, + octave_sparse_sort_idxl* j); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,42 @@ +2005-02-25 John W. Eaton + + Sparse merge. + + 2005-01-23 David Bateman + + * sparse/randperm.m: Delete duplicate randperm.m. + + 2005-01-10 John W. Eaton + + * sparse/Makefile.in: New file. + * configure.in (AC_CONFIG_FILES): Add sparse/Makefile to the list. + + 2005-01-07 David Bateman + + * set/unique.m: import file from octave-forge. + + 2005-01-05 David Bateman + + * Makefile.in: include sparse directory in SUBDIRS. + + 2004-12-30 John W. Eaton + + * sparse/nzmax.m: Delete (there is an nzmax function in + src/DLD-FUNCTIONS/sparse.cc). + + 2004-12-28 John W. Eaton + + Merge of sparse code from David Bateman and + Andy Adler . + + * sparse/colperm.m, sparse/nonzeros.m, sparse/nzmax.m, + sparse/randperm.m, sparse/spalloc.m, sparse/spconvert.m, + sparse/spdiags.m, sparse/speye.m, sparse/spfun.m, sparse/sphcat.m, + sparse/spones.m, sparse/sprand.m, sparse/sprandn.m, + sparse/spstats.m, sparse/spvcat.m, sparse/spy.m: New files. + + * sparse: New directory. + 2005-02-22 John W. Eaton * polynomial/residue.m: Force prepad to always create row vectors. diff --git a/scripts/Makefile.in b/scripts/Makefile.in --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -31,8 +31,8 @@ SUBDIRS = audio control deprecated elfun finance general image io \ linear-algebra miscellaneous plot polynomial quaternion \ - set signal specfun special-matrix startup statistics \ - strings time + set signal sparse specfun special-matrix startup \ + statistics strings time DISTSUBDIRS = $(SUBDIRS) diff --git a/scripts/configure.in b/scripts/configure.in --- a/scripts/configure.in +++ b/scripts/configure.in @@ -34,8 +34,9 @@ finance/Makefile general/Makefile image/Makefile io/Makefile \ linear-algebra/Makefile miscellaneous/Makefile plot/Makefile \ polynomial/Makefile quaternion/Makefile set/Makefile \ - signal/Makefile specfun/Makefile special-matrix/Makefile \ - startup/Makefile statistics/Makefile statistics/base/Makefile \ - statistics/distributions/Makefile statistics/models/Makefile \ - statistics/tests/Makefile strings/Makefile time/Makefile]) + signal/Makefile sparse/Makefile specfun/Makefile \ + special-matrix/Makefile startup/Makefile statistics/Makefile \ + statistics/base/Makefile statistics/distributions/Makefile \ + statistics/models/Makefile statistics/tests/Makefile \ + strings/Makefile time/Makefile]) AC_OUTPUT diff --git a/scripts/sparse/Makefile.in b/scripts/sparse/Makefile.in new file mode 100644 --- /dev/null +++ b/scripts/sparse/Makefile.in @@ -0,0 +1,69 @@ +# +# Makefile for octave's scripts/sparse directory +# +# John W. Eaton +# jwe@bevo.che.wisc.edu +# University of Wisconsin-Madison +# Department of Chemical Engineering + +TOPDIR = ../.. + +script_sub_dir = sparse + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +include $(TOPDIR)/Makeconf + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +SOURCES = *.m + +DISTFILES = Makefile.in $(SOURCES) + +FCN_FILES = $(wildcard $(srcdir)/*.m) +FCN_FILES_NO_DIR = $(notdir $(FCN_FILES)) + +BINDISTFILES = $(FCN_FILES) + +all: +.PHONY: all + +install install-strip: + $(do-script-install) +.PHONY: install install-strip + +uninstall: + $(do-script-uninstall) +.PHONY: uninstall + +clean: +.PHONY: clean + +tags: $(SOURCES) + ctags $(SOURCES) + +TAGS: $(SOURCES) + etags $(SOURCES) + +mostlyclean: clean +.PHONY: mostlyclean + +distclean: clean + rm -f Makefile +.PHONY: distclean + +maintainer-clean: distclean + rm -f tags TAGS +.PHONY: maintainer-clean + +dist: + ln $(DISTFILES) ../../`cat ../../.fname`/scripts/sparse +.PHONY: dist + +bin-dist: + ln $(BINDISTFILES) ../../`cat ../../.fname`/scripts/sparse +.PHONY: bin-dist diff --git a/scripts/sparse/colperm.m b/scripts/sparse/colperm.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/colperm.m @@ -0,0 +1,30 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{p} =} colperm (@var{s}) +## Returns the column permutations such that the columns of +## @code{@var{s} (:, @var{p})} are ordered in terms of increase number +## of non-zero elements. If @var{s} is symmetric, then @var{p} is chosen +## such that @code{@var{s} (@var{p}, @var{p})} orders the rows and +## columns with increasing number of non zeros elements. +## @end deftypefn + +function p = colperm (s) + [i, j] = spfind (s); + idx = find (diff ([j; Inf]) != 0); + [dummy, p] = sort (idx - [0; idx(1:(end-1))]); +endfunction diff --git a/scripts/sparse/nonzeros.m b/scripts/sparse/nonzeros.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/nonzeros.m @@ -0,0 +1,19 @@ +## Copyright (C) 2004 Paul Kienzle +## +## This program is free software and is in the public domain + +## -*- texinfo -*- +## @deftypefn {Function File} {} nonzeros (@var{s}) +## Returns a vector of the non-zero values of the sparse matrix @var{s}. +## @end deftypefn + +function t = nonzeros(s) + if issparse(s) + [i,j,t] = spfind(s); + else + [i,j,t] = find(s); + endif +endfunction + +%!assert(nonzeros([1,2;3,0]),[1;3;2]) +%!assert(nonzeros(sparse([1,2;3,0])),[1;3;2]) diff --git a/scripts/sparse/spalloc.m b/scripts/sparse/spalloc.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spalloc.m @@ -0,0 +1,43 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{s} =} spalloc (@var{r}, @var{c}, @var{nz}) +## Returns an empty sparse matrix of size @var{r}-by-@var{c}. As Octave +## resizes sparse matrices at the first opportunity, so that no additional +## space is needed, the argument @var{nz} is ignored. This function is +## provided only for compatiability reasons. +## +## It should be noted that this means that code like +## +## @example +## k = 5; +## nz = r * k; +## s = spalloc (r, c, nz) +## for j = 1:c +## idx = randperm (r); +## s (:, j) = [zeros(r - k, 1); rand(k, 1)] (idx); +## endfor +## @end example +## +## will reallocate memory at each step. It is therefore vitally important +## that code like this is vectorized as much as possible. +## @end deftypefn +## @seealso{sparse, nzmax} + +function s = spalloc (r, c, nz) + s = sparse (r, c); +endfunction diff --git a/scripts/sparse/spconvert.m b/scripts/sparse/spconvert.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spconvert.m @@ -0,0 +1,43 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{x} =} spconvert (@var{m}) +## This function converts for a simple sparse matrix format easily +## produced by other programs into Octave's internal sparse format. The +## input @var{x} is either a 3 or 4 column real matrix, containing +## the row, column, real and imaginary parts of the elements of the +## sparse matrix. An element with a zero real and imaginay part can +## be used to force a particular matrix size. +## @end deftypefn + +function s = spconvert (m) + + if issparse(m) + s = m; + else + sz = size(m); + if (nargin != 1 || !ismatrix(m) || !isreal(m) || length(sz) != 2 || + (sz(2) != 3 && sz(2) != 4)) + error ("spconvert: input matrix must be either sparse or a three or four column"); + error (" real matrix"); + elseif (sz(2) == 3) + s = sparse (m(:,1), m(:,2), m(:,3)); + else + s = sparse (m(:,1), m(:,2), m(:,3) + 1i*m(:,4)); + endif + endif +endfunction diff --git a/scripts/sparse/spdiags.m b/scripts/sparse/spdiags.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spdiags.m @@ -0,0 +1,92 @@ +## Copyright (C) 2000-2001 Paul Kienzle +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {function File} {[@var{b}, @var{c}]} = spdiags (@var{a}) +## @deftypefnx {function File} {@var{b}} = spdiags (@var{a}, @var{c}) +## @deftypefnx {function File} {@var{b}} = spdiags (@var{v}, @var{c}, @var{a}) +## @deftypefnx {function File} {@var{b}} = spdiags (@var{v}, @var{c}, @var{m}, @var{n}) +## A generalization of the function @code{spdiag}. Called with a single +## input argument, the non-zero diagonals @var{c} of @var{A} are extracted. +## With two arguments the diagonals to extract are given by the vector +## @var{c}. +## +## The other two forms of @code{spdiags} modify the input matrix by +## replacing the diagonals. They use the columns of @var{v} to replace +## the columns represented by the vector @var{c}. If the sparse matrix +## @var{a} is defined then the diagonals of this matrix are replaced. +## Otherwise a matrix of @var{m} by @var{n} is created with the +## diagonals given by @var{v}. +## +## Negative values of @var{c} representive diagonals below the main +## diagonal, and positive values of @var{c} diagonals above the main +## diagonal. +## +## For example +## +## @example +## @group +## spdiags (reshape (1:12, 4, 3), [-1 0 1], 5, 4) +## @result{} 5 10 0 0 +## 1 6 11 0 +## 0 2 7 12 +## 0 0 3 8 +## 0 0 0 4 +## @end group +## @end example +## +## @end deftypefn + +function [A, c] = spdiags(v,c,m,n) + + wfi = warn_fortran_indexing; + unwind_protect + warn_fortran_indexing = 0; + + if nargin == 1 || nargin == 2 + ## extract nonzero diagonals of v into A,c + [i,j,v,nr,nc] = spfind(v); + if nargin == 1 + c = unique(j-i); # c contains the active diagonals + endif + ## FIXME: we can do this without a loop if we are clever + offset = max(min(c,nc-nr),0); + A = zeros(min(nr,nc),length(c)); + for k=1:length(c) + idx = find(j-i == c(k)); + A(j(idx)-offset(k),k) = v(idx); + end + elseif nargin == 3 + ## Replace specific diagonals c of m with v,c + [nr,nc] = size(m); + B = spdiags(m,c); + A = m - spdiags(B,c,nr,nc) + spdiags(v,c,nr,nc); + else + ## Create new matrix of size mxn using v,c + [j,i,v] = find(v); + offset = max(min(c(:),n-m),0); + j+=offset(i); + i=j-c(:)(i); + idx = i>0 & i<=m & j>0 & j<=n; + A = sparse(i(idx),j(idx),v(idx),m,n); + + endif + + unwind_protect_cleanup + warn_fortran_indexing = wfi; + end_unwind_protect + +endfunction diff --git a/scripts/sparse/speye.m b/scripts/sparse/speye.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/speye.m @@ -0,0 +1,55 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} speye (@var{m}) +## @deftypefnx {Function File} {@var{y} =} speye (@var{m}, @var{n}) +## @deftypefnx {Function File} {@var{y} =} speye (@var{sz}) +## Returns a sparse identity matrix. This is significantly more +## efficient than @code{sparse (eye (@var{m}))} as the full matrix +## is not constructed. +## +## Called with a single argument a square matrix of size @var{m} by +## @var{m} is created. Otherwise a matrix of @var{m} by @var{n} is +## created. If called with a single vector argument, this argument +## is taken to be the size of the matrix to create. +## @end deftypefn + +function s = speye(m,n) + if (nargin == 1) + if (isvector (m) && length(m) == 2) + n = m(2); + m = m(1); + elseif (isscalar (m)) + n = m; + else + error ("speye: invalid matrix dimension"); + endif + else + if (!isscalar (m) || !isscalar (n)) + error ("speye: invalid matrix dimension"); + endif + endif + + lo = min([m,n]); + s = sparse(1:lo,1:lo,1,m,n); +endfunction + +%!assert(issparse(speye(4))) +%!assert(speye(4),sparse(1:4,1:4,1)) +%!assert(speye(2,4),sparse(1:2,1:2,1,2,4)) +%!assert(speye(4,2),sparse(1:2,1:2,1,4,2)) +%!assert(speye([4,2]),sparse(1:2,1:2,1,4,2)) diff --git a/scripts/sparse/spfun.m b/scripts/sparse/spfun.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spfun.m @@ -0,0 +1,49 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} spfun (@var{f},@var{x}) +## Compute @code{f(@var{x})} for the non-zero values of @var{x}. +## This results in a sparse matrix with the same structure as +## @var{x}. The function @var{f} can be passed as a string, a +## function handle or an inline function. +## @end deftypefn + +function t = spfun(f,s) + if (nargin != 2) + usage ("spfun(f,s)") + endif + + if issparse(s) + [i,j,v,m,n] = spfind(s); + else + [i,j,v] = find(s); + [m,n] = size(s); + end + + if (isa (f, "function handle") || isa (f, "inline function")) + t = sparse(i,j,f(v),m,n); + else + t = sparse(i,j,feval(f,v),m,n); + endif + +endfunction + +%!assert(spfun('exp',[1,2;3,0]),sparse([exp(1),exp(2);exp(3),0])) +%!assert(spfun('exp',sparse([1,2;3,0])),sparse([exp(1),exp(2);exp(3),0])) +%!assert(spfun(@exp,[1,2;3,0]),sparse([exp(1),exp(2);exp(3),0])) +%!assert(spfun(@exp,sparse([1,2;3,0])),sparse([exp(1),exp(2);exp(3),0])) + diff --git a/scripts/sparse/sphcat.m b/scripts/sparse/sphcat.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/sphcat.m @@ -0,0 +1,34 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} sphcat (@var{a1}, @var{a2}, @dots{}, @var{aN}) +## Return the horizontal concatenation of sparse matrices. This function +## is obselete and @code{horzcat} should be used +## @end deftypefn +## @seealso {spvcat, vertcat, horzcat, cat} + +function y = sphcat (varargin) + + persistent sphcat_warned = false; + + if (!sphcat_warned) + sphcat_warned = true; + warning ("sphcat: This function is depreciated. Use horzcat instead"); + endif + + y = horzcat (varargin{:}); +endfunction diff --git a/scripts/sparse/spones.m b/scripts/sparse/spones.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spones.m @@ -0,0 +1,35 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} spones (@var{x}) +## Replace the non-zero entries of @var{x} with ones. This creates a +## sparse matrix with the same structure as @var{x}. +## @end deftypefn + +function s = spones(s) + if issparse(s) + [i,j,v,m,n] = spfind(s); + else + [i,j,v] = find(s); + [m,n] = size(s); + end + s = sparse(i,j,1,m,n); +endfunction + +%!assert(issparse(spones([1,2;3,0]))) +%!assert(spones([1,2;3,0]),sparse([1,1;1,0])) +%!assert(spones(sparse([1,2;3,0])),sparse([1,1;1,0])) diff --git a/scripts/sparse/sprand.m b/scripts/sparse/sprand.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/sprand.m @@ -0,0 +1,58 @@ +## Copyright (C) 2004 Paul Kienzle +## +## This program is free software and is in the public domain + +## -*- texinfo -*- +## @deftypefn {Function File} {} sprand (@var{m}, @var{n}, @var{d}) +## @deftypefnx {Function File} {} sprand (@var{s}) +## Generate a random sparse matrix. The size of the matrix will be +## @var{m} by @var{n}, with a density of values given by @var{d}. +## @var{d} should be between 0 and 1. Values will be normally +## distributed with mean of zero and variance 1. +## +## Note: sometimes the actual density may be a bit smaller than @var{d}. +## This is unlikely to happen for large really sparse matrices. +## +## If called with a single matrix argument, a random sparse matrix is +## generated wherever the matrix @var{S} is non-zero. +## @end deftypefn +## @seealso{sprandn} + + +## This program is public domain +## Author: Paul Kienzle +## +## Changelog: +## +## Piotr Krzyzanowski +## 2004-09-27 use Paul's hint to allow larger random matrices +## at the price of sometimes lower density than desired +## David Bateman +## 2004-10-20 Texinfo help and copyright message + +function S = sprand (m, n, d) + if nargin == 1 + [i,j,v,nr,nc] = spfind(m); + S = sparse (i,j,rand(size(v)),nr,nc); + elseif nargin == 3 + mn = n*m; + k = round(d*mn); # how many entries in S would be satisfactory? + idx=unique(fix(rand(min(k*1.01,k+10),1)*mn))+1; + # idx contains random numbers in [1,mn] + # generate 1% or 10 more random values than necessary + # in order to reduce the probability that there are less than k + # distinct values; + # maybe a better strategy could be used + # but I don't think it's worth the price + k = min(length(idx),k); # actual number of entries in S + j = floor((idx(1:k)-1)/m); + i = idx(1:k) - j*m; + if isempty(i) + S = sparse(m,n); + else + S = sparse(i,j+1,rand(k,1),m,n); + endif + else + usage("sprand(m,n,density) OR sprand(S)"); + endif +endfunction diff --git a/scripts/sparse/sprandn.m b/scripts/sparse/sprandn.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/sprandn.m @@ -0,0 +1,49 @@ +## Copyright (C) 2004 Paul Kienzle +## +## This program is free software and is in the public domain + +## -*- texinfo -*- +## @deftypefn {Function File} {} sprand (@var{m}, @var{n}, @var{d}) +## @deftypefnx {Function File} {} sprand (@var{s}) +## Generate a random sparse matrix. The size of the matrix will be +## @var{m} by @var{n}, with a density of values given by @var{d}. +## @var{d} should be between 0 and 1. Values will be normally +## distributed with mean of zero and variance 1. +## +## Note: sometimes the actual density may be a bit smaller than @var{d}. +## This is unlikely to happen for large really sparse matrices. +## +## If called with a single matrix argument, a random sparse matrix is +## generated wherever the matrix @var{S} is non-zero. +## @end deftypefn +## @seealso{sprandn} + +## This program is public domain +## Author: Paul Kienzle + +function S = sprandn(m,n,d) + if nargin == 1 + [i,j,v,nr,nc] = spfind(m); + S = sparse(i,j,randn(size(v)),nr,nc); + elseif nargin == 3 + mn = m*n; + k = round(d*mn); + idx=unique(fix(rand(min(k*1.01,k+10),1)*mn))+1; + # idx contains random numbers in [1,mn] + # generate 1% or 10 more random values than necessary + # in order to reduce the probability that there are less than k + # distinct values; + # maybe a better strategy could be used + # but I don't think it's worth the price + k = min(length(idx),k); # actual number of entries in S + j = floor((idx(1:k)-1)/m); + i = idx(1:k) - j*m; + if isempty(i) + S = sparse(m,n); + else + S = sparse(i,j+1,randn(k,1),m,n); + endif + else + usage("sprandn(m,n,density) OR sprandn(S)"); + endif +endfunction diff --git a/scripts/sparse/spstats.m b/scripts/sparse/spstats.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spstats.m @@ -0,0 +1,48 @@ +## Copyright (C) 2004 Paul Kienzle +## +## This program is free software and is in the public domain + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{count}, @var{mean}, @var{var}]} = spstats (@var{s}) +## @deftypefnx {Function File} {[@var{count}, @var{mean}, @var{var}]} = spstats (@var{s}, @var{j}) +## Return the stats for the non-zero elements of the sparse matrix @var{s}. +## @var{count} is the number of non-zeros in each column, @var{mean} +## is the mean of the non-zeros in each column, and @var{var} is the +## variance of the non-zeros in each column. +## +## Called with two output arguments, if @var{s} is the data and @var{j} +## is the bin number for the data, compute the stats for each bin. In +## this case, bins can contain data values of zero, whereas with +## @code{spstats (@var{s})} the zeros may disappear. +## @end deftypefn + +function [count,mean,var] = spstats(S,j) + if nargin < 1 || nargin > 2 + usage("[count, mean, var] = spstats(S) OR spstats(x,j)"); + endif + + [n, m] = size (S); + if nargin == 1 + [i,j,v] = spfind (S); + else + v = S; + i = 1:length (v); + S = sparse (i, j, v); + endif + + count = spsum (sparse (i, j, 1, n, m)); + if (nargout > 1) + mean = spsum(S) ./ count; + end + if (nargout > 2) + ## XXX FIXME XXX Variance with count = 0 or 1? + diff = S - sparse (i, j, mean(j), n, m); + var = spsum (diff .* diff) ./ (count - 1); + end +endfunction + +%!test +%! [n,m,v] = spstats([1 2 1 2 3 4],[2 2 1 1 1 1]); +%! assert(n,[4,2]); +%! assert(m,[10/4,3/2],10*eps); +%! assert(v,[5/3,1/2],10*eps); diff --git a/scripts/sparse/spvcat.m b/scripts/sparse/spvcat.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spvcat.m @@ -0,0 +1,34 @@ +## Copyright (C) 2004 David Bateman & Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} spvcat (@var{a1}, @var{a2}, @dots{}, @var{aN}) +## Return the vertical concatenation of sparse matrices. This function +## is obselete and @code{vertcat} should be used +## @end deftypefn +## @seealso {sphcat, vertcat, horzcat, cat} + +function y = spvcat (varargin) + + persistent spvcat_warned = false; + + if (!spvcat_warned) + spvcat_warned = true; + warning ("spvcat: This function is depreciated. Use vertcat instead"); + endif + + y = vertcat (varargin{:}); +endfunction diff --git a/scripts/sparse/spy.m b/scripts/sparse/spy.m new file mode 100644 --- /dev/null +++ b/scripts/sparse/spy.m @@ -0,0 +1,50 @@ +## Copyright (C) 1998-2004 Andy Adler +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} spy (@var{x}) +## Plot the sparsity pattern of the sparse matrix @var{x}. +## @end deftypefn + +function spy(S) + if issparse(S) + [i,j,s,m,n]= spfind(S); + else + [i,j,s] = find(S); + [m,n] = size(S); + endif + + arp = automatic_replot; + unwind_protect + automatic_replot = 0; + + eval(sprintf('gset nokey')) + eval(sprintf('gset yrange [0:%d] reverse',m+1)) + eval(sprintf('gset xrange [0:%d] noreverse',n+1)) + + if (length(i)<1000) + plot(j,i,'*'); + else + plot(j,i,'.'); + endif + + #TODO: we should store the reverse state so we don't undo it + gset yrange [0:1] noreverse + axis; + unwind_protect_cleanup + automatic_replot = arp; + end_unwind_protect +endfunction diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,282 @@ +2005-02-25 John W. Eaton + + Sparse merge. + + 2005-02-25 John W. Eaton + + * DLD-SRC/rand.cc (Frand): Accept "state" as an alias for "seed". + + * DLD-SRC/dispatch.cc: New file. + * Makefile.in (DLD_XSRC): Add it to the list. + + 2005-02-13 David Bateman + + * ov-fcn-inline.h, DLD-FUNCTIONS/spparms.cc, DLD-FUNCTIONS/gcd.cc: + Remove additional licensing clause, with authors permission + + * ov-base-sparse.h: New constructor to cache SparseType, not yet + used + * ov-re-sparse.h: likewise + * ov-cx-sparse.h: likewise + * ov.h: Likewise + + * sparse-xdiv.cc: Remove spparms umfpack flag + + * DLD-FUNCTIONS/spparms.cc: Warning that umfpack flag is ignored. + + 2005-01-16 David Bateman + + * ls-mat5.cc (read_mat5_integer_data): Change "T &m" to "T *m" and + instantiate with values like octave_int8 rather than int8NDArray. + Modify function to fit + (read_mat5_binary_element): Use new form of read_mat_integer_data + to read data directly into sparse matrix + (write_mat5_integer_data): Change "const T &m" to "T *m", etc. New + instantiation with int. + (save_mat5_binary_element): Modify to save sparse data + + 2005-01-15 David Bateman + + * data.cc (do_cat): Use first non-empty matrix as base for + concatenation. + * pt-mat.cc (tree_matrix::rvalue): ditto. + + 2005-01-14 John W. Eaton + + * ov.cc (do_cat_op): When checking for empty args, use + all_zero_dims, not numel. + * ov.h (octave_value::all_zero_dims): New function. + + * ov-bool-sparse.cc (try_narrowing_conversion): Convert to + bool_matrix, not matrix. + + 2005-01-13 David Bateman + + * data.cc (make_diag): Use numel not capacity to remove ambiguity. + * ov.h (octave_value::capacity): New virtual funtion. + * ov-base.h (octave_base_value::capacity): New function calls numel. + * data.cc (Freshape): Use arg.numel() rather than arg.dims().numel() + since sparse numel now consistent. + * symtab.h (symbol_record::symbol_def::capacity, + symbol_record::capacity): New methods. + * symtab.cc (symbol_record::print_symbol_info_line, + symbol_table::parse_whos_line_format, symbol_table::maybe_list): + used capacity() and not numel() to properly assess size of + sparse objects. + * ov-base-sparse.h (octave_base_sparse::capacity): New function, + (octave_base_sparse::numel): Delete. + * ov-re-sparse.cc (octave_sparse_matrix::streamoff_array_value): + Only fill from non-zero elements of sparse array. + * DLD-FUNCTIONS/splu.cc (Fsplu): Change use of nelem to numel. + * ov.cc (do_cat_op): Early return for concatenation with empty + objects. + + 2005-01-12 John W. Eaton + + * DLD-FUNCTIONS/find.cc (Ffind): Make it work for character strings. + + 2005-01-11 John W. Eaton + + * OPERATORS/op-double-conv.cc: New conversions for sparse_matrix + and sparse_bool_matrix to matrix. + + 2005-01-11 David Bateman + + * ov-base-sparse.h (octave_base_sparse::any, + octave_base_sparse::all): Use new constructors, etc as pointed out + by JWE. + + 2005-01-10 John W. Eaton + + * DLD-FUNCTIONS/sparse.cc (MINMAX_BODY, Fspatan2, make_spdiag): + Write retval(0) = result instead of retval(0) = octave_value (result). + * DLD-FUNCTIONS/splu.cc (Fsplu): Likewise. + + 2005-01-08 David Bateman + + * ls-mat5.cc (read_mat5_integer_data): Instantiate for Array + (read_mat5_binary_element): Add code to read sparse matrices + saved in matlab v5 format + + 2005-01-07 David Bateman + + * OPERATORS/op-bm-sbm.cc, OPERATORS/op-b-sbm.cc, + OPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc, + OPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc, + OPERATORS/op-m-scm.cc, OPERATORS/op-m-sm.cc, + OPERATORS/op-sbm-b.cc, OPERATORS/op-sbm-bm.cc, + OPERATORS/op-sbm-sbm.cc, OPERATORS/op-scm-cm.cc, + OPERATORS/op-scm-cs.cc, OPERATORS/op-scm-m.cc, + OPERATORS/op-scm-s.cc, OPERATORS/op-scm-scm.cc, + OPERATORS/op-scm-sm.cc, OPERATORS/op-sm-cm.cc, + OPERATORS/op-sm-cs.cc, OPERATORS/op-sm-m.cc, + OPERATORS/op-sm-s.cc, OPERATORS/op-sm-scm.cc, + OPERATORS/op-sm-sm.cc, OPERATORS/op-s-scm.cc, + OPERATORS/op-s-sm.cc: New octave_value constructors allow + macros from ops.h to be used rather than sparse-ops.h. Remove + other explicit uses of maybe_mutate. + + * sparse-ops.h: delete file. + + * colamd.cc (Fcolamd, Fsymamd, Fetree): Remove no longer needed + use of get_rep() and use the sparse matrix conversion functions + directly. + + * data.cc (Freshape): Use arg.dims().numel() rather than + arg.numel() due to definition of numel for sparse matrices. + + * sparse.cc (Ffull, Fspfind, SPARSE_DIM_ARG_BODY, MINMAX_BODY, + Fspatan2, make_spdiag): Convert to use new octave_value sparse + constructors, sparse matrix conversion functions and remove + maybe_mutate calls. + (Fspreshape): Delete + + * splu.cc (Fsplu): Remove remaining explicit octave_value + construction. + + * ov-base-sparse.h (do_index_op, resize, reshape, permute, squeeze): + Move these methods from the derived classes. + * ov-base-spase.cc (do_index_op): Move this method from the derived + classes. + * ov-bool-sparse.h (do_index_op, resize, reshape, permute, squeeze): + delete. + * ov-re-spase.cc (do_index_op): delete. + * ov-cx-sparse.h (do_index_op, resize, reshape, permute, squeeze): + delete. + * ov-cx-spase.cc (do_index_op): delete. + * ov-bool-spase.cc (do_index_op): delete. + * ov-re-sparse.h (do_index_op, resize, reshape, permute, squeeze): + delete. + + * DLD-FUNCTIONS/spdet.cc (Fspdet): Remove use of SparseDet and + SparseComplexDET classes and use DET and ComplexDET classes. + + * DLD-FUNCTIONS/colamd.cc op-bm-sbm.cc OPERATORS/op-b-sbm.cc + OPERATORS/op-cm-scm.cc OPERATORS/op-cm-sm.cc OPERATORS/op-cs-scm.cc + OPERATORS/op-cs-sm.cc OPERATORS/op-fil-sbm.cc OPERATORS/op-fil-scm.cc + OPERATORS/op-fil-sm.cc OPERATORS/op-m-scm.cc OPERATORS/op-m-sm.cc + OPERATORS/op-sbm-b.cc OPERATORS/op-sbm-bm.cc OPERATORS/op-sbm-sbm.cc + OPERATORS/op-scm-cm.cc OPERATORS/op-scm-cs.cc OPERATORS/op-scm-m.cc + OPERATORS/op-scm-s.cc OPERATORS/op-scm-scm.cc OPERATORS/op-scm-sm.cc + OPERATORS/op-sm-cm.cc OPERATORS/op-sm-cs.cc OPERATORS/op-sm-m.cc + OPERATORS/op-sm-s.cc OPERATORS/op-sm-scm.cc OPERATORS/op-sm-sm.cc + OPERATORS/op-s-scm.cc OPERATORS/op-s-sm.cc ov-base-sparse.cc + ov-base-sparse.h ov-bool-sparse.cc ov-bool-sparse.h ov-cx-sparse.cc + ov-cx-sparse.h ov-re-sparse.cc ov-re-sparse.h sparse-base-lu.cc + sparse-base-lu.h DLD-FUNCTIONS/sparse.cc sparse-xdiv.cc sparse-xdiv.h + sparse-xpow.cc sparse-xpow.h DLD-FUNCTIONS/spdet.cc + DLD-FUNCTIONS/splu.cc DLD-FUNCTIONS/spparms.cc: Remove additional + licensing clause with authors permission. + + 2005-01-05 David Bateman + + * DLD-FUNCTIONS/colamd.cc: Rename from colamdoct.cc. Base colamd.h + now found in COLAMD/colamd.h. + (Fcolamd): Return value is now used. + (Fsymamd): ditto. + + * Makefile.in: include colamd.cc in DLD_XSRC. + + * ov.h (sparse_matrix_value, sparse_complex_matrix_value, + sparse_bool_matrix_value): New virtual functions + + * ov-base.cc (octave_base_value::sparse_matrix_value, + octave_base_value::sparse_complex_matrix_value, + octave_base_value::sparse_bool_matrix_value): New default sparse + matrix extraction functions. + + * ov-base.h (sparse_matrix_value, sparse_complex_matrix_value, + sparse_bool_matrix_value): Declare them. + + * ov-re-mat.cc (octave_matrix::sparse_matrix_value, + octave_matrix::sparse_complex_matrix_value): Conversion functions. + + * ov-re-mat.h (sparse_matrix_value, sparse_complex_matrix_value): + Declare them. + + * ov-cx-mat.cc (octave_complex_matrix::sparse_matrix_value, + octave_complex_matrix::sparse_complex_matrix_value): Conversion + functions. + + * ov-cx-mat.h (sparse_matrix_value, sparse_complex_matrix_value): + Declare them. + + * ov-bool-mat.h (sparse_matrix_value, sparse_complex_matrix_value, + sparse_bool_matrix_value): Conversion functions. + + * DLD_FUNCTIONS/spdet.cc (Fspdet): Use the above constructors + and conversion functions. + * DLD_FUNCTIONS/splu.cc (Fsplu): ditto. + + 2004-12-30 John W. Eaton + + * DLD-FUNCTIONS/splu.cc (Fsplu): Avoid shadow warnings. + + * sparse-xpow.cc (elem_xpow): Delete unsed variables. + * sparse-xdiv.cc (x_el_div): Likewise. + + * DLD-FUNCTIONS/det.cc (Fdet): Delete unused argument nargout. + * DLD-FUNCTIONS/spdet.cc (Fspdet): Likewise. + + * DLD-FUNCTIONS/sparse.cc (Fnzmax): Return a value. + + * ov.cc, ov.h (octave_value::octave_value (const SparseMatrix&), + (octave_value::octave_value (const SparseBoolMatrix&), + (octave_value::octave_value (const SparseComplexMatrix&)): + New constructors. + + 2004-12-29 John W. Eaton + + * DLD-FUNCTIONS/sparse.cc (SPARSE_DIM_ARG_BODY): Rename from + DEFUN_DLD_SPARSE_DIM_ARG. Omit HELP arg. Omit DEFUN_DLD, so the + macro only defines the function body. + (Fspprod, Fspcumprod, Fspsum, Fspcumsum, Fspsumsq): Define with + DEFUN_DLD, not DEFUN_DLD_SPARSE_DIM_ARG. Use SPARSE_DIM_ARG_BODY + to define function body. + + * DLD-FUNCTIONS/sparse.cc (load_sparse_type, sparse_type_loaded): + Delete function, variable, and all uses. + * ov.cc: Include ov-bool-sparse.h, ov-re-sparse.h, ov-cx-sparse.h. + (install_types): Register sparse types. + + Merge of sparse code from David Bateman and + Andy Adler . + + * sparse-xdiv.cc, sparse-xpow.cc: New files. + * Makefile.in (DIST_SRC): Add them to the list. + + * sparse-ops.h sparse-xdiv.h, sparse-xpow.h: New files. + * Makefile.in (INCLUDES): Add them to the list. + + * DLD-FUNCTIONS/colamdoct.cc, DLD-FUNCTIONS/sparse.cc, + DLD-FUNCTIONS/spdet.cc, DLD-FUNCTIONS/splu.cc, + DLD-FUNCTIONS/spparms.cc: New files. + * Makefile.in (DLD_XSRC): Add them to the list. + + * ov-base-sparse.cc, ov-base-sparse.h, ov-bool-sparse.cc, + ov-bool-sparse.h, ov-cx-sparse.cc, ov-cx-sparse.h, + ov-re-sparse.cc, ov-re-sparse.h: New files. + * Makefile.in (OV_SPARSE_SRC, OV_SPARSE_INCLUDES): New lists. + (OV_SRC): Add $(OV_SPARSE_SRC) to the list. + (INCLUDES): Add $(OV_SPARSE_INCLUDES) to the list. + + * OPERATORS/op-bm-sbm.cc, OPERATORS/op-b-sbm.cc, + OPERATORS/op-cm-scm.cc, OPERATORS/op-cm-sm.cc, + OPERATORS/op-cs-scm.cc, OPERATORS/op-cs-sm.cc, + OPERATORS/op-fil-sbm.cc, OPERATORS/op-fil-scm.cc, + OPERATORS/op-fil-sm.cc, OPERATORS/op-m-scm.cc, + OPERATORS/op-m-sm.cc, OPERATORS/op-sbm-b.cc, + OPERATORS/op-sbm-bm.cc, OPERATORS/op-sbm-sbm.cc, + OPERATORS/op-scm-cm.cc, OPERATORS/op-scm-cs.cc, + OPERATORS/op-scm-m.cc, OPERATORS/op-scm-s.cc, + OPERATORS/op-scm-scm.cc, OPERATORS/op-scm-sm.cc, + OPERATORS/op-sm-cm.cc, OPERATORS/op-sm-cs.cc, + OPERATORS/op-sm-m.cc, OPERATORS/op-sm-s.cc, + OPERATORS/op-sm-scm.cc, OPERATORS/op-sm-sm.cc, + OPERATORS/op-s-scm.cc, OPERATORS/op-s-sm.cc: New files. + * Makefile.in (SPARSE_OP_XSRC): New list. + (OP_XSRC): Add $(SPARSE_OP_XSRC) to the list. + 2005-02-23 John W. Eaton * parse.y (fold (tree_binary_expression*)): Skip constant folding diff --git a/src/DLD-FUNCTIONS/colamd.cc b/src/DLD-FUNCTIONS/colamd.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/colamd.cc @@ -0,0 +1,726 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// This is the octave interface to colamd, which bore the copyright given +// in the help of the functions. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "ov.h" +#include "defun-dld.h" +#include "pager.h" +#include "ov-re-mat.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// External COLAMD functions in C +extern "C" { +#include "COLAMD/colamd.h" +} + +// The symmetric column elimination tree code take from the Davis LDL code. +// Copyright given elsewhere in this file. +static +void symetree (const int *ridx, const int *cidx, int *Parent, int *P, int n) +{ + OCTAVE_LOCAL_BUFFER (int, Flag, n); + OCTAVE_LOCAL_BUFFER (int, Pinv, (P ? n : 0)); + if (P) + // If P is present then compute Pinv, the inverse of P + for (int k = 0 ; k < n ; k++) + Pinv [P [k]] = k ; + + for (int k = 0 ; k < n ; k++) + { + // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) + Parent [k] = n ; // parent of k is not yet known + Flag [k] = k ; // mark node k as visited + int kk = (P) ? (P [k]) : (k) ; // kth original, or permuted, column + int p2 = cidx [kk+1] ; + for (int p = cidx [kk] ; p < p2 ; p++) + { + // A (i,k) is nonzero (original or permuted A) + int i = (Pinv) ? (Pinv [ridx [p]]) : (ridx [p]) ; + if (i < k) + { + // follow path from i to root of etree, stop at flagged node + for ( ; Flag [i] != k ; i = Parent [i]) + { + // find parent of i if not yet determined + if (Parent [i] == n) + Parent [i] = k ; + Flag [i] = k ; // mark i as visited + } + } + } + } +} + +// The elimination tree post-ordering code below is taken from SuperLU +static inline +int make_set (int i, int *pp) +{ + pp[i] = i; + return i; +} + +static inline +int link (int s, int t, int *pp) +{ + pp[s] = t; + return t; +} + +static inline +int find (int i, int *pp) +{ + register int p, gp; + + p = pp[i]; + gp = pp[p]; + while (gp != p) { + pp[i] = gp; + i = gp; + p = pp[i]; + gp = pp[p]; + } + return (p); +} + +static +int etdfs (int v, int *first_kid, int *next_kid, int *post, int postnum) +{ + for (int w = first_kid[v]; w != -1; w = next_kid[w]) { + postnum = etdfs (w, first_kid, next_kid, post, postnum); + } + post[postnum++] = v; + + return postnum; +} + +static +void TreePostorder(int n, int *parent, int *post) +{ + // Allocate storage for working arrays and results + OCTAVE_LOCAL_BUFFER (int, first_kid, n+1); + OCTAVE_LOCAL_BUFFER (int, next_kid, n+1); + + // Set up structure describing children + for (int v = 0; v <= n; first_kid[v++] = -1); + for (int v = n-1; v >= 0; v--) + { + int dad = parent[v]; + next_kid[v] = first_kid[dad]; + first_kid[dad] = v; + } + + // Depth-first search from dummy root vertex #n + etdfs (n, first_kid, next_kid, post, 0); +} + +static +void coletree (const int *ridx, const int *colbeg, int *colend, + int *parent, int nr, int nc) +{ + OCTAVE_LOCAL_BUFFER (int, root, nc); + OCTAVE_LOCAL_BUFFER (int, pp, nc); + OCTAVE_LOCAL_BUFFER (int, firstcol, nr); + + // Compute firstcol[row] = first nonzero column in row + for (int row = 0; row < nr; firstcol[row++] = nc); + for (int col = 0; col < nc; col++) + for (int p = colbeg[col]; p < colend[col]; p++) + { + int row = ridx[p]; + if (firstcol[row] > col) + firstcol[row] = col; + } + + // Compute etree by Liu's algorithm for symmetric matrices, + // except use (firstcol[r],c) in place of an edge (r,c) of A. + // Thus each row clique in A'*A is replaced by a star + // centered at its first vertex, which has the same fill. + for (int col = 0; col < nc; col++) + { + int cset = make_set (col, pp); + root[cset] = col; + parent[col] = nc; + for (int p = colbeg[col]; p < colend[col]; p++) + { + int row = firstcol[ridx[p]]; + if (row >= col) + continue; + int rset = find (row, pp); + int rroot = root[rset]; + if (rroot != col) + { + parent[rroot] = col; + cset = link (cset, rset, pp); + root[cset] = col; + } + } + } +} + +DEFUN_DLD (colamd, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{p} =} colamd (@var{s})\n\ +@deftypefnx {Loadable Function} {@var{p} =} colamd (@var{s}, @var{knobs})\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} colamd (@var{s})\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} colamd (@var{s}, @var{knobs})\n\ +\n\ +Column approximate minimum degree permutation. @code{@var{p} = colamd\n\ +(@var{s})} returns the column approximate minimum degree permutation\n\ +vector for the sparse matrix @var{s}. For a non-symmetric matrix @var{s},\n\ +@code{@var{s} (:,@var{p})} tends to have sparser LU factors than @var{s}.\n\ +The Cholesky factorization of @code{@var{s} (:,@var{p})' * @var{s}\n\ +(:,@var{p})} also tends to be sparser than that of @code{@var{s}' *\n\ +@var{s}}.\n\ +\n\ +@var{knobs} is an optional two-element input vector. If @var{s} is\n\ +m-by-n, then rows with more than @code{(@var{knobs} (1)) * @var{n}}\n\ +entries are ignored. Columns with more than @code{(@var{knobs} (2)) *\n\ +@var{m}} entries are removed prior to ordering, and ordered last in the\n\ +output permutation @var{p}. If the knobs parameter is not present, then\n\ +0.5 is used instead, for both @code{@var{knobs} (1)} and\n\ +@code{@var{knobs} (2)}. @code{@var{knobs} (3)} controls the printing of\n\ +statistics and error messages.\n\ +\n\ +@var{stats} is an optional 20-element output vector that provides data\n\ +about the ordering and the validity of the input matrix @var{s}. Ordering\n\ +statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1)} and\n\ +@code{@var{stats} (2)} are the number of dense or empty rows and columns\n\ +ignored by COLAMD and @code{@var{stats} (3)} is the number of garbage\n\ +collections performed on the internal data structure used by COLAMD\n\ +(roughly of size @code{2.2 * nnz(@var{s}) + 4 * @var{m} + 7 * @var{n}}\n\ +integers).\n\ +\n\ +Octave built-in functions are intended to generate valid sparse matrices,\n\ +with no duplicate entries, with ascending row indices of the nonzeros\n\ +in each column, with a non-negative number of entries in each column (!)\n\ +and so on. If a matrix is invalid, then COLAMD may or may not be able\n\ +to continue. If there are duplicate entries (a row index appears two or\n\ +more times in the same column) or if the row indices in a column are out\n\ +of order, then COLAMD can correct these errors by ignoring the duplicate\n\ +entries and sorting each column of its internal copy of the matrix\n\ +@var{s} (the input matrix @var{s} is not repaired, however). If a matrix\n\ +is invalid in other ways then COLAMD cannot continue, an error message is\n\ +printed, and no output arguments (@var{p} or @var{stats}) are returned.\n\ +COLAMD is thus a simple way to check a sparse matrix to see if it's\n\ +valid.\n\ +\n\ +@code{@var{stats} (4:7)} provide information if COLAMD was able to\n\ +continue. The matrix is OK if @code{@var{stats} (4)} is zero, or 1 if\n\ +invalid. @code{@var{stats} (5)} is the rightmost column index that is\n\ +unsorted or contains duplicate entries, or zero if no such column exists.\n\ +@code{@var{stats} (6)} is the last seen duplicate or out-of-order row\n\ +index in the column index given by @code{@var{stats} (5)}, or zero if no\n\ +such row index exists. @code{@var{stats} (7)} is the number of duplicate\n\ +or out-of-order row indices. @code{@var{stats} (8:20)} is always zero in\n\ +the current version of COLAMD (reserved for future use).\n\ +\n\ +The ordering is followed by a column elimination tree post-ordering.\n\ +\n\ +The authors of the code itself are Stefan I. Larimore and Timothy A.\n\ +Davis (davis@@cise.ufl.edu), University of Florida. The algorithm was\n\ +developed in collaboration with John Gilbert, Xerox PARC, and Esmond\n\ +Ng, Oak Ridge National Laboratory. (see\n\ +@url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ +@end deftypefn\n\ +@seealso{colperm, symamd}") +{ + octave_value_list retval; + int nargin = args.length (); + int spumoni = 0; + + if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) + usage ("colamd: incorrect number of input and/or output arguments"); + else + { + // Get knobs + OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); + colamd_set_defaults (knobs); + + // Check for user-passed knobs + if (nargin == 2) + { + NDArray User_knobs = args(1).array_value (); + int nel_User_knobs = User_knobs.length (); + + if (nel_User_knobs > 0) + knobs [COLAMD_DENSE_ROW] = User_knobs (COLAMD_DENSE_ROW); + if (nel_User_knobs > 1) + knobs [COLAMD_DENSE_COL] = User_knobs (COLAMD_DENSE_COL) ; + if (nel_User_knobs > 2) + spumoni = (int) User_knobs (2); + } + + // print knob settings if spumoni is set + if (spumoni > 0) + { + octave_stdout << "colamd: dense row fraction: " + << knobs [COLAMD_DENSE_ROW] << std::endl; + octave_stdout << "colamd: dense col fraction: " + << knobs [COLAMD_DENSE_COL] << std::endl; + } + + int n_row, n_col, nnz; + int *ridx, *cidx; + SparseComplexMatrix scm; + SparseMatrix sm; + + if (args(0).class_name () == "sparse") + { + if (args(0).is_complex_type ()) + { + scm = args(0). sparse_complex_matrix_value (); + n_row = scm.rows (); + n_col = scm.cols (); + nnz = scm.nnz (); + ridx = scm.xridx (); + cidx = scm.xcidx (); + } + else + { + sm = args(0).sparse_matrix_value (); + + n_row = sm.rows (); + n_col = sm.cols (); + nnz = sm.nnz (); + ridx = sm.xridx (); + cidx = sm.xcidx (); + } + } + else + { + if (args(0).is_complex_type ()) + sm = SparseMatrix (real (args(0).complex_matrix_value ())); + else + sm = SparseMatrix (args(0).matrix_value ()); + + n_row = sm.rows (); + n_col = sm.cols (); + nnz = sm.nnz (); + ridx = sm.xridx (); + cidx = sm.xcidx (); + } + + // Allocate workspace for colamd + OCTAVE_LOCAL_BUFFER (int, p, n_col+1); + for (int i = 0; i < n_col+1; i++) + p[i] = cidx [i]; + + int Alen = colamd_recommended (nnz, n_row, n_col); + OCTAVE_LOCAL_BUFFER (int, A, Alen); + for (int i = 0; i < nnz; i++) + A[i] = ridx [i]; + + // Order the columns (destroys A) + OCTAVE_LOCAL_BUFFER (int, stats, COLAMD_STATS); + if (!colamd (n_row, n_col, Alen, A, p, knobs, stats)) + { + colamd_report (stats) ; + error ("colamd: internal error!"); + return retval; + } + + // column elimination tree post-ordering (reuse variables) + OCTAVE_LOCAL_BUFFER (int, colbeg, n_col + 1); + OCTAVE_LOCAL_BUFFER (int, colend, n_col + 1); + OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); + + for (int i = 0; i < n_col; i++) + { + colbeg[i] = cidx[p[i]]; + colend[i] = cidx[p[i]+1]; + } + + coletree (ridx, colbeg, colend, etree, n_row, n_col); + + // Calculate the tree post-ordering + TreePostorder (n_col, etree, colbeg); + + // return the permutation vector + NDArray out_perm (dim_vector (1, n_col)); + for (int i = 0; i < n_col; i++) + out_perm(i) = p [colbeg [i]] + 1; + + retval (0) = out_perm; + + // print stats if spumoni > 0 + if (spumoni > 0) + colamd_report (stats) ; + + // Return the stats vector + if (nargout == 2) + { + NDArray out_stats (dim_vector (1, COLAMD_STATS)); + for (int i = 0 ; i < COLAMD_STATS ; i++) + out_stats (i) = stats [i] ; + retval(1) = out_stats; + + // fix stats (5) and (6), for 1-based information on + // jumbled matrix. note that this correction doesn't + // occur if symamd returns FALSE + out_stats (COLAMD_INFO1) ++ ; + out_stats (COLAMD_INFO2) ++ ; + } + } + + return retval; +} + +DEFUN_DLD (symamd, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{p} =} symamd (@var{s})\n\ +@deftypefnx {Loadable Function} {@var{p} =} symamd (@var{s}, @var{knobs})\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} symamd (@var{s})\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} symamd (@var{s}, @var{knobs})\n\ +\n\ +For a symmetric positive definite matrix @var{s}, returns the permutation\n\ +vector p such that @code{@var{s} (@var{p}, @var{p})} tends to have a\n\ +sparser Cholesky factor than @var{s}. Sometimes SYMAMD works well for\n\ +symmetric indefinite matrices too. The matrix @var{s} is assumed to be\n\ +symmetric; only the strictly lower triangular part is referenced. @var{s}\n\ +must be square.\n\ +\n\ +@var{knobs} is an optional input argument. If @var{s} is n-by-n, then\n\ +rows and columns with more than @code{@var{knobs} (1) * @var{n}} entries\n\ +are removed prior to ordering, and ordered last in the output permutation\n\ +@var{p}. If the @var{knobs} parameter is not present, then the default of\n\ +0.5 is used instead. @code{@var{knobs} (2)} controls the printing of\n\ +statistics and error messages.\n\ +\n\ +@var{stats} is an optional 20-element output vector that provides data\n\ +about the ordering and the validity of the input matrix @var{s}. Ordering\n\ +statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1) =\n\ +@var{stats} (2)} is the number of dense or empty rows and columns\n\ +ignored by SYMAMD and @code{@var{stats} (3)} is the number of garbage\n\ +collections performed on the internal data structure used by SYMAMD\n\ +(roughly of size @code{8.4 * nnz (tril (@var{s}, -1)) + 9 * @var{n}}\n\ +integers).\n\ +\n\ +Octave built-in functions are intended to generate valid sparse matrices,\n\ +with no duplicate entries, with ascending row indices of the nonzeros\n\ +in each column, with a non-negative number of entries in each column (!)\n\ +and so on. If a matrix is invalid, then SYMAMD may or may not be able\n\ +to continue. If there are duplicate entries (a row index appears two or\n\ +more times in the same column) or if the row indices in a column are out\n\ +of order, then SYMAMD can correct these errors by ignoring the duplicate\n\ +entries and sorting each column of its internal copy of the matrix S (the\n\ +input matrix S is not repaired, however). If a matrix is invalid in\n\ +other ways then SYMAMD cannot continue, an error message is printed, and\n\ +no output arguments (@var{p} or @var{stats}) are returned. SYMAMD is\n\ +thus a simple way to check a sparse matrix to see if it's valid.\n\ +\n\ +@code{@var{stats} (4:7)} provide information if SYMAMD was able to\n\ +continue. The matrix is OK if @code{@var{stats} (4)} is zero, or 1\n\ +if invalid. @code{@var{stats} (5)} is the rightmost column index that\n\ +is unsorted or contains duplicate entries, or zero if no such column\n\ +exists. @code{@var{stats} (6)} is the last seen duplicate or out-of-order\n\ +row index in the column index given by @code{@var{stats} (5)}, or zero\n\ +if no such row index exists. @code{@var{stats} (7)} is the number of\n\ +duplicate or out-of-order row indices. @code{@var{stats} (8:20)} is\n\ +always zero in the current version of SYMAMD (reserved for future use).\n\ +\n\ +The ordering is followed by a column elimination tree post-ordering.\n\ +\n\ +\n\ +The authors of the code itself are Stefan I. Larimore and Timothy A.\n\ +Davis (davis@@cise.ufl.edu), University of Florida. The algorithm was\n\ +developed in collaboration with John Gilbert, Xerox PARC, and Esmond\n\ +Ng, Oak Ridge National Laboratory. (see\n\ +@url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ +@end deftypefn\n\ +@seealso{colperm, colamd}") +{ + octave_value_list retval; + int nargin = args.length (); + int spumoni = 0; + + if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) + usage ("symamd: incorrect number of input and/or output arguments"); + else + { + // Get knobs + OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); + colamd_set_defaults (knobs); + + // Check for user-passed knobs + if (nargin == 2) + { + NDArray User_knobs = args(1).array_value (); + int nel_User_knobs = User_knobs.length (); + + if (nel_User_knobs > 0) + knobs [COLAMD_DENSE_ROW] = User_knobs (COLAMD_DENSE_ROW); + if (nel_User_knobs > 1) + spumoni = (int) User_knobs (1); + } + + // print knob settings if spumoni is set + if (spumoni > 0) + octave_stdout << "symamd: dense row/col fraction: " + << knobs [COLAMD_DENSE_ROW] << std::endl; + + int n_row, n_col, nnz; + int *ridx, *cidx; + SparseMatrix sm; + SparseComplexMatrix scm; + + if (args(0).class_name () == "sparse") + { + if (args(0).is_complex_type ()) + { + scm = args(0).sparse_complex_matrix_value (); + n_row = scm.rows (); + n_col = scm.cols (); + nnz = scm.nnz (); + ridx = scm.xridx (); + cidx = scm.xcidx (); + } + else + { + sm = args(0).sparse_matrix_value (); + n_row = sm.rows (); + n_col = sm.cols (); + nnz = sm.nnz (); + ridx = sm.xridx (); + cidx = sm.xcidx (); + } + } + else + { + if (args(0).is_complex_type ()) + sm = SparseMatrix (real (args(0).complex_matrix_value ())); + else + sm = SparseMatrix (args(0).matrix_value ()); + + n_row = sm.rows (); + n_col = sm.cols (); + nnz = sm.nnz (); + ridx = sm.xridx (); + cidx = sm.xcidx (); + } + + if (n_row != n_col) + { + error ("symamd: matrix must be square"); + return retval; + } + + // Allocate workspace for symamd + OCTAVE_LOCAL_BUFFER (int, perm, n_col+1); + OCTAVE_LOCAL_BUFFER (int, stats, COLAMD_STATS); + if (!symamd (n_col, ridx, cidx, perm, knobs, stats, &calloc, &free)) + { + symamd_report (stats) ; + error ("symamd: internal error!") ; + return retval; + } + + // column elimination tree post-ordering + OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); + symetree (ridx, cidx, etree, perm, n_col); + + // Calculate the tree post-ordering + OCTAVE_LOCAL_BUFFER (int, post, n_col + 1); + TreePostorder (n_col, etree, post); + + // return the permutation vector + NDArray out_perm (dim_vector (1, n_col)); + for (int i = 0; i < n_col; i++) + out_perm(i) = perm [post [i]] + 1; + + retval (0) = out_perm; + + // print stats if spumoni > 0 + if (spumoni > 0) + symamd_report (stats) ; + + // Return the stats vector + if (nargout == 2) + { + NDArray out_stats (dim_vector (1, COLAMD_STATS)); + for (int i = 0 ; i < COLAMD_STATS ; i++) + out_stats (i) = stats [i] ; + retval(1) = out_stats; + + // fix stats (5) and (6), for 1-based information on + // jumbled matrix. note that this correction doesn't + // occur if symamd returns FALSE + out_stats (COLAMD_INFO1) ++ ; + out_stats (COLAMD_INFO2) ++ ; + } + } + + return retval; +} + +DEFUN_DLD (etree, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{p} =} etree (@var{s})\n\ +@deftypefnx {Loadable Function} {@var{p} =} etree (@var{s}, @var{typ})\n\ +@deftypefnx {Loadable Function} {[@var{p}, @var{q}] =} etree (@var{s}, @var{typ})\n\ +\n\ +Returns the elimination tree for the matrix @var{s}. By default @var{s}\n\ +is assumed to be symmetric and the symmetric elimination tree is\n\ +returned. The argument @var{typ} controls whether a symmetric or\n\ +column elimination tree is returned. Valid values of @var{typ} are\n\ +'sym' or 'col', for symmetric or column elimination tree respectively\n\ +\n\ +Called with a second argument, @dfn{etree} also returns the postorder\n\ +permutations on the tree.\n\ +@end deftypefn") +{ + octave_value_list retval; + int nargin = args.length (); + + if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) + usage ("etree: incorrect number of input and/or output arguments"); + else + { + int n_row, n_col, nnz; + int *ridx, *cidx; + bool is_sym = true; + SparseMatrix sm; + SparseComplexMatrix scm; + + if (args(0).class_name () == "sparse") + { + if (args(0).is_complex_type ()) + { + scm = args(0).sparse_complex_matrix_value (); + n_row = scm.rows (); + n_col = scm.cols (); + nnz = scm.nnz (); + ridx = scm.xridx (); + cidx = scm.xcidx (); + } + else + { + sm = args(0).sparse_matrix_value (); + n_row = sm.rows (); + n_col = sm.cols (); + nnz = sm.nnz (); + ridx = sm.xridx (); + cidx = sm.xcidx (); + } + + } + else + { + error ("etree: must be called with a sparse matrix"); + return retval; + } + + if (nargin == 2) + if (args(1).is_string ()) + { + std::string str = args(1).string_value (); + if (str.find("C") == 0 || str.find("c") == 0) + is_sym = false; + } + else + { + error ("etree: second argument must be a string"); + return retval; + } + + // column elimination tree post-ordering (reuse variables) + OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); + + + if (is_sym) + { + if (n_row != n_col) + { + error ("etree: matrix is marked as symmetric, but not square"); + return retval; + } + symetree (ridx, cidx, etree, NULL, n_col); + } + else + { + OCTAVE_LOCAL_BUFFER (int, colbeg, n_col); + OCTAVE_LOCAL_BUFFER (int, colend, n_col); + + for (int i = 0; i < n_col; i++) + { + colbeg[i] = cidx[i]; + colend[i] = cidx[i+1]; + } + + coletree (ridx, colbeg, colend, etree, n_row, n_col); + } + + NDArray tree (dim_vector (1, n_col)); + for (int i = 0; i < n_col; i++) + // We flag a root with n_col while Matlab does it with zero + // Convert for matlab compatiable output + if (etree[i] == n_col) + tree (i) = 0; + else + tree (i) = etree[i] + 1; + + retval (0) = tree; + + if (nargout == 2) + { + // Calculate the tree post-ordering + OCTAVE_LOCAL_BUFFER (int, post, n_col + 1); + TreePostorder (n_col, etree, post); + + NDArray postorder (dim_vector (1, n_col)); + for (int i = 0; i < n_col; i++) + postorder (i) = post[i] + 1; + + retval (1) = postorder; + } + } + + return retval; +} + +DEFUN_DLD (symbfact, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{r}]} = symbfact (@var{s}, @var{typ})\n\ +\n\ +Performs a symbolic factorization analysis on the sparse matrix @var{s}.\n\ +@end deftypefn") +{ + error ("symbfact: not implemented yet"); + return octave_value (); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/DLD-FUNCTIONS/det.cc b/src/DLD-FUNCTIONS/det.cc --- a/src/DLD-FUNCTIONS/det.cc +++ b/src/DLD-FUNCTIONS/det.cc @@ -33,7 +33,7 @@ #include "oct-obj.h" #include "utils.h" -DEFUN_DLD (det, args, nargout, +DEFUN_DLD (det, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {[@var{d}, @var{rcond}] = } det (@var{a})\n\ Compute the determinant of @var{a} using @sc{Lapack}. Return an estimate\n\ @@ -111,9 +111,7 @@ } } else - { - gripe_wrong_type_arg ("det", arg); - } + gripe_wrong_type_arg ("det", arg); return retval; } diff --git a/src/DLD-FUNCTIONS/dispatch.cc b/src/DLD-FUNCTIONS/dispatch.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/dispatch.cc @@ -0,0 +1,599 @@ +/* + +Copyright (C) 2001 John W. Eaton and Paul Kienzle + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "defun-dld.h" +#include "ov.h" +#include "ov-fcn.h" +#include "ov-typeinfo.h" +#include "pager.h" +#include "parse.h" +#include "symtab.h" +#include "variables.h" + +// XXX FIXME XXX should be using a map from type_id->name, rather +// than type_name->name + +template class std::map; + +typedef std::map Table; + +class +octave_dispatch : public octave_function +{ +public: + + // XXX FIXME XXX need to handle doc strings of dispatched functions, for + // example, by appending "for (,...) see " for each + // time dispatch(f,type,name) is called. + octave_dispatch (const std::string &nm) + : octave_function (nm, "Overloaded function"), tab (), base (nm), + has_alias (false) + { } + + // XXX FIXME XXX if we get deleted, we should restore the original + // symbol_record from base before dying. + ~octave_dispatch (void) { } + + bool is_builtin_function (void) const { return true; } + + octave_function *function_value (bool) { return this; } + + octave_value do_index_op (const octave_value_list&, int) + { + error ("dispatch: do_index_op"); + return octave_value (); + } + + octave_value subsref (const std::string&, + const std::list&) + { + error ("dispatch: subsref (str, list)"); + panic_impossible (); + return octave_value (); + } + + octave_value_list subsref (const std::string& type, + const std::list& idx, + int nargout); + + octave_value_list do_multi_index_op (int, const octave_value_list&); + + void add (const std::string t, const std::string n); + + void clear (const std::string t); + + void print (std::ostream& os, bool pr_as_read=false) const; + +private: + + Table tab; + std::string base; + bool has_alias; + + octave_dispatch (void) + : octave_function (), tab (), base (), has_alias (false) { } + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA + + DECLARE_OCTAVE_ALLOCATOR +}; + +DEFINE_OCTAVE_ALLOCATOR (octave_dispatch); + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_dispatch, + "overloaded function", "function"); + +void +octave_dispatch::add (const std::string t, const std::string n) +{ + if (tab.count (t) > 0 && tab[t] != n) + warning ("replacing %s(%s,...)->%s with %s", + base.c_str (), t.c_str (), tab[t].c_str (), n.c_str ()); + + tab[t] = n; + + if (t == "any") + has_alias = true; +} + +void +octave_dispatch::clear (const std::string t) +{ + tab.erase (t); + + if (t == "any") + has_alias = false; +} + +octave_value_list +octave_dispatch::subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '(': + retval = do_multi_index_op (nargout, idx.front ()); + break; + + case '{': + case '.': + { + const std::string nm = type_name (); + error ("%s cannot be indexed with %c", nm.c_str (), type[0]); + } + break; + + default: + panic_impossible (); + } + + if (idx.size () > 1) + retval = retval(0).next_subsref (type, idx); + + return retval; +} + +static octave_function* +builtin (const std::string& base) +{ + octave_function *fcn = 0; + + // Check if we are overriding a builtin function. This is the + // case if builtin is protected. + symbol_record *builtin = fbi_sym_tab->lookup ("builtin:" + base, 0); + + if (! builtin) + error ("builtin record has gone missing"); + + if (error_state) + return fcn; + + if (builtin->is_read_only ()) + { + // builtin is read only, so checking for updates is pointless + if (builtin->is_function ()) + fcn = builtin->def().function_value (); + else + error ("builtin %s is not a function", base.c_str ()); + } + else + { + // Check that builtin is up to date. + + // Don't try to fight octave's function name handling + // mechanism. Instead, move dispatch record out of the way, + // and restore the builtin to its original name. + symbol_record *dispatch = fbi_sym_tab->lookup (base, 0); + if (! dispatch) + error ("dispatch record has gone missing"); + + dispatch->unprotect (); + + fbi_sym_tab->rename (base, "dispatch:" + base); + + fbi_sym_tab->rename ("builtin:" + base, base); + + // check for updates to builtin function; ignore errors that + // appear (they interfere with renaming), and remove the updated + // name from the current symbol table. XXX FIXME XXX check that + // updating a function updates it in all contexts --- it may be + // that it is updated only in the current symbol table, and not + // the caller. I believe this won't be a problem because the + // caller will go through the same logic and end up with the + // newer version. + fcn = is_valid_function (base, "dispatch", 1); + int cache_error = error_state; + error_state = 0; + curr_sym_tab->clear_function (base); + + // Move the builtin function out of the way and restore the + // dispatch fuction. + // XXX FIXME XXX what if builtin wants to protect itself? + symbol_record *found=fbi_sym_tab->lookup (base, 0); + bool readonly = found->is_read_only (); + found->unprotect (); + fbi_sym_tab->rename (base, "builtin:" + base); + fbi_sym_tab->rename ("dispatch:" + base, base); + if (readonly) + found->protect (); + dispatch->protect (); + + // remember if there were any errors. + error_state = cache_error; + } + + return fcn; +} + +static bool +any_arg_is_magic_colon (const octave_value_list& args) +{ + int nargin = args.length (); + + for (int i = 0; i < nargin; i++) + if (args(i).is_magic_colon ()) + return true; + + return false; +} + + +octave_value_list +octave_dispatch::do_multi_index_op (int nargout, const octave_value_list& args) +{ + octave_value_list retval; + + if (error_state) return retval; + + if (any_arg_is_magic_colon (args)) + { + ::error ("invalid use of colon in function argument list"); + return retval; + } + + // If more than one argument, check if argument template matches any + // overloaded functions. Also provide a catch-all '*' type to provide + // single level pseudo rename and replace functionality. + if (args.length () > 0 && tab.count (args(0).type_name ()) > 0) + retval = feval (tab[args(0).type_name()], args, nargout); + else if (has_alias) + retval = feval (tab["any"], args, nargout); + else + { + octave_function *fcn = builtin (base); + if (! error_state && fcn) + retval = fcn->do_multi_index_op (nargout, args); + } + + return retval; +} + +void +octave_dispatch::print (std::ostream& os, bool) const +{ + os << "Overloaded function " << base << std::endl; + + for (Table::const_iterator it = tab.begin (); it != tab.end (); it++) + os << base << "(" << it->first << ",...)->" + << it->second << "(" << it->first << ",...)" + << std::endl; +} + +DEFUN_DLD (builtin, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@dots{}]} builtin (@var{f}, @dots{})\n\ +Call the base function @var{f} even if @var{f} is overloaded to\n\ +some other function for the given type signature.\n\ +@end deftypefn\n\ +@seealso{dispatch}") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin > 0) + { + const std::string name (args(0).string_value ()); + + if (error_state) + return retval; + + symbol_record *sr = fbi_sym_tab->lookup (name, 0); + if (sr->def().type_id () == octave_dispatch::static_type_id ()) + { + octave_function *fcn = builtin (name); + + if (!error_state && fcn) + retval = fcn->do_multi_index_op (nargout, + args.splice (0, 1, retval)); + } + else + retval = feval (name, args, nargout); + } + else + print_usage ("builtin"); + + return retval; +} + +DEFUN_DLD (dispatch_help, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} dispatch_help (@var{name}, @dots{})\n\ +Delayed loading of help messages for dispatched functions.\n\ +@end deftypefn\n\ +@seealso{builtin, dispatch}") +{ + octave_value_list retval; + + int nargin = args.length (); + + for (int i = 0; i < nargin; i++) + { + if (args(i).is_string ()) + { + const std::string name (args(i).string_value ()); + + if (error_state) + return retval; + + symbol_record *sr = fbi_sym_tab->lookup (name, false); + + if (sr) + { + std::string help = sr->help (); + + if (help[0] == '<' && help[1] == '>' + && sr->def().type_id () == octave_dispatch::static_type_id ()) + { + builtin (name); + + symbol_record *builtin_record + = fbi_sym_tab->lookup ("builtin:" + name, 0); + + help.replace (0, 2, builtin_record->help ()); + + sr->document (help); + } + } + } + } + + return feval ("builtin:help", args, nargout); +} + +static void +dispatch_record (const std::string &f, const std::string &n, + const std::string &t) +{ + // find the base function in the symbol table, loading it if it + // is not already there; if it is already a dispatch, then bonus + + symbol_record *sr = fbi_sym_tab->lookup (f, true); + + if (sr->def().type_id () != octave_dispatch::static_type_id ()) + { + // Preserve mark_as_command status + bool iscommand = sr->is_command (); + + // Not an overloaded name, so if only display or clear then we are done + if (t.empty ()) + return; + + // sr is the base symbol; rename it to keep it safe. When we need + // it we will rename it back again. + if (sr->is_read_only ()) + { + sr->unprotect (); + fbi_sym_tab->rename (f, "builtin:" + f); + sr = fbi_sym_tab->lookup (f, true); + sr->protect (); + } + else + fbi_sym_tab->rename (f, "builtin:" + f); + + std::string basedoc ("<>"); + + if (! sr->help().empty ()) + basedoc = sr->help (); + + // Problem: when a function is first called a new record + // is created for it in the current symbol table, so calling + // dispatch on a function that has already been called, we + // should also clear it from all existing symbol tables. + // This is too much work, so we will only do it for the + // top level symbol table. We can't use the clear_function() + // method, because it won't clear builtin functions. Instead + // we check if the symbol is a function and clear it then. This + // won't properly clear shadowed functions, or functions in + // other namespaces (such as the current, if called from a + // function). + symbol_record *local = top_level_sym_tab->lookup (f, false); + if (local && local->is_function ()) + local->clear (); + + // Build a new dispatch object based on the function definition + octave_dispatch *dispatch = new octave_dispatch (f); + + // Create a symbol record for the dispatch object. + sr = fbi_sym_tab->lookup (f, true); + sr->unprotect (); + sr->define (octave_value (dispatch), symbol_record::BUILTIN_FUNCTION); + // std::cout << "iscommand('"<mark_as_command(); + sr->document (basedoc + "\n\nOverloaded function\n"); + sr->make_eternal (); // XXX FIXME XXX why?? + sr->mark_as_static (); + sr->protect (); + } + + // clear/replace/extend the map with the new type-function pair + const octave_dispatch& rep + = reinterpret_cast (sr->def().get_rep ()); + + if (t.empty ()) + // XXX FIXME XXX should return the list if nargout > 1 + rep.print (octave_stdout); + else if (n.empty ()) + { + // XXX FIXME XXX should we eliminate the dispatch function if + // there are no more elements? + // XXX FIXME XXX should clear the " $t:\w+" from the help string. + // XXX FIXME XXX -- seems bad to cast away const here... + octave_dispatch& xrep = const_cast (rep); + + xrep.clear (t); + } + else + { + // XXX FIXME XXX -- seems bad to cast away const here... + octave_dispatch& xrep = const_cast (rep); + + xrep.add (t, n); + + if (! sr->help().empty ()) + sr->document (sr->help() + "\n " + n + "(" + t + ",...)"); + } +} + +DEFUN_DLD (dispatch, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} dispatch (@var{f}, @var{r}, @var{type})\n\ +\n\ +Replace the function @var{f} with a dispatch so that function @var{r}\n\ +is called when @var{f} is called with the first argument of the named\n\ +@var{type}. If the type is @var{any} then call @var{r} if no other type\n\ +matches. The original function @var{f} is accessible using\n\ +@code{builtin (@var{f}, @dots{}).\n\ +\n\ +If @var{r} is omitted, clear dispatch function associated with @var{type}.\n\ +\n\ +If both @var{r} and @var{type} are omitted, list dispatch functions\n\ +for @var{f}\n\ +@end deftypefn\n\ +@seealso{builtin}") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin < 1 || nargin > 3) + { + print_usage ("dispatch"); + return retval; + } + + std::string f, t, n; + if (nargin > 0) + f = args(0).string_value (); + + if (nargin == 2) + t = args(1).string_value (); + else if (nargin > 2) + { + n = args(1).string_value (); + t = args(2).string_value (); + } + + if (error_state) + return retval; + + static bool register_type = true; + + // register dispatch function type if you have not already done so + if (register_type) + { + octave_dispatch::register_type (); + register_type = false; + fbi_sym_tab->lookup("dispatch")->mark_as_static (); + dispatch_record ("help", "dispatch_help", "string"); + } + + dispatch_record (f, n, t); + + return retval; +} + +/* + +%!test # builtin function replacement +%! dispatch('sin','length','string') +%! assert(sin('abc'),3) +%! assert(sin(0),0,10*eps); +%!test # 'any' function +%! dispatch('sin','exp','any') +%! assert(sin(0),1,eps); +%! assert(sin('abc'),3); +%!test # 'builtin' function +%! assert(builtin('sin',0),0,eps); +%! builtin('eval','x=1;'); +%! assert(x,1); +%!test # clear function mapping +%! dispatch('sin','string') +%! dispatch('sin','any') +%! assert(sin(0),0,10*eps); +%!test # oct-file replacement +%! dispatch('fft','length','string') +%! assert(fft([1,1]),[2,0]); +%! assert(fft('abc'),3) +%! dispatch('fft','string'); +%!test # m-file replacement +%! dispatch('hamming','length','string') +%! assert(hamming(1),1) +%! assert(hamming('abc'),3) +%! dispatch('hamming','string') + +%!test # override preloaded builtin +%! evalin('base','cos(1);'); +%! dispatch('cos','length','string') +%! evalin('base',"assert(cos('abc'),3)"); +%! evalin('base',"assert(cos(0),1,eps)"); +%! dispatch('cos','string') +%!test # override pre-loaded oct-file +%! evalin('base','qr(1);'); +%! dispatch('qr','length','string') +%! evalin('base',"assert(qr('abc'),3)"); +%! evalin('base',"assert(qr(1),1)"); +%! dispatch('qr','string'); +%!test # override pre-loaded m-file +%! evalin('base','hanning(1);'); +%! dispatch('hanning','length','string') +%! evalin('base','assert(hanning("abc"),3)'); +%! evalin('base','assert(hanning(1),1)'); +%! dispatch('hanning','string'); + +XXX FIXME XXX I would rather not create dispatch_x/dispatch_y +in the current directory! I don't want them installed accidentally. + +%!test # replace base m-file +%! system("echo 'function a=dispatch_x(a)'>dispatch_x.m"); +%! dispatch('dispatch_x','length','string') +%! assert(dispatch_x(3),3) +%! assert(dispatch_x('a'),1) +%! pause(1); +%! system("echo 'function a=dispatch_x(a),++a;'>dispatch_x.m"); +%! assert(dispatch_x(3),4) +%! assert(dispatch_x('a'),1) +%!test +%! system("rm dispatch_x.m"); + +%!test # replace dispatch m-file +%! system("echo 'function a=dispatch_y(a)'>dispatch_y.m"); +%! dispatch('hello','dispatch_y','complex scalar') +%! assert(hello(3i),3i) +%! pause(1); +%! system("echo 'function a=dispatch_y(a),++a;'>dispatch_y.m"); +%! assert(hello(3i),1+3i) +%!test +%! system("rm dispatch_y.m"); + +XXX FIXME XXX add tests for preservation of mark_as_command status. + +*/ diff --git a/src/DLD-FUNCTIONS/gcd.cc b/src/DLD-FUNCTIONS/gcd.cc --- a/src/DLD-FUNCTIONS/gcd.cc +++ b/src/DLD-FUNCTIONS/gcd.cc @@ -17,10 +17,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -In addition to the terms of the GPL, you are permitted to link -this program with any Open Source program, as defined by the -Open Source Initiative (www.opensource.org) - */ #ifdef HAVE_CONFIG_H diff --git a/src/DLD-FUNCTIONS/rand.cc b/src/DLD-FUNCTIONS/rand.cc --- a/src/DLD-FUNCTIONS/rand.cc +++ b/src/DLD-FUNCTIONS/rand.cc @@ -72,7 +72,7 @@ { retval = octave_rand::distribution (); } - else if (s_arg == "seed") + else if (s_arg == "seed" || s_arg == "state") { retval = octave_rand::seed (); } @@ -179,7 +179,9 @@ if (nargin == 2 && tmp.is_string ()) { - if (tmp.string_value () == "seed") + std::string ts = tmp.string_value (); + + if (ts == "seed" || ts == "state") { double d = args(1).double_value (); diff --git a/src/DLD-FUNCTIONS/sort.cc b/src/DLD-FUNCTIONS/sort.cc --- a/src/DLD-FUNCTIONS/sort.cc +++ b/src/DLD-FUNCTIONS/sort.cc @@ -25,6 +25,8 @@ #include #endif +#include + #include "lo-mappers.h" #include "quit.h" diff --git a/src/DLD-FUNCTIONS/sparse.cc b/src/DLD-FUNCTIONS/sparse.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/sparse.cc @@ -0,0 +1,1369 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "variables.h" +#include "utils.h" +#include "pager.h" +#include "defun-dld.h" +#include "gripes.h" +#include "quit.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" +#include "ov-bool-sparse.h" + +static bool +is_sparse (const octave_value& arg) +{ + return (arg.class_name () == "sparse"); +} + +DEFUN_DLD (issparse, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} issparse (@var{expr})\n\ +Return 1 if the value of the expression @var{expr} is a sparse matrix.\n\ +@end deftypefn") +{ + if (args.length() != 1) + { + print_usage("issparse"); + return octave_value (); + } + else + return octave_value (is_sparse (args(0))); +} + +DEFUN_DLD (sparse, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{sparse_val} =} sparse (...)\n\ +SPARSE: create a sparse matrix\n\ +\n\ +sparse can be called in the following ways:\n\ +\n\ +@enumerate\n\ +@item @var{S} = sparse(@var{A}) where @var{A} is a full matrix\n\ +\n\ +@item @var{S} = sparse(@var{A},1) where @var{A} is a full matrix, result\n\ +is forced back to a full matrix is resulting matrix is sparse\n\ +\n\ +@item @var{S} = sparse(@var{i},@var{j},@var{s},@var{m},@var{n},@var{nzmax}) where\n\ + @itemize @w \n\ +@var{i},@var{j} are integer index vectors (1 x nnz) @* \n\ +@var{s} is the vector of real or complex entries (1 x nnz) @* \n\ +@var{m},@var{n} are the scalar dimentions of S @* \n\ +@var{nzmax} is ignored (here for compatability with Matlab) @* \n\ +\n\ + if multiple values are specified with the same @var{i},@var{j}\n\ + position, the corresponding values in @var{s} will be added\n\ + @end itemize\n\ +\n\ +@item The following usages are equivalent to (2) above:\n\ + @itemize @w \n\ +@var{S} = sparse(@var{i},@var{j},@var{s},@var{m},@var{n})@*\n\ +@var{S} = sparse(@var{i},@var{j},@var{s},@var{m},@var{n},'summation')@*\n\ +@var{S} = sparse(@var{i},@var{j},@var{s},@var{m},@var{n},'sum')@*\n\ + @end itemize\n\ +\n\ +@item @var{S} = sparse(@var{i},@var{j},@var{s},@var{m},@var{n},'unique')@*\n\ +\n\ + @itemize @w \n\ +same as (2) above, except that rather than adding,\n\ +if more than two values are specified for the same @var{i},@var{j}\n\ +position, then the last specified value will be kept\n\ + @end itemize\n\ +\n\ +@item @var{S}= sparse(@var{i},@var{j},@var{sv}) uses @var{m}=max(@var{i}), @var{n}=max(@var{j})\n\ +\n\ +@item @var{S}= sparse(@var{m},@var{n}) does sparse([],[],[],@var{m},@var{n},0)\n\ +\n\ +@var{sv}, and @var{i} or @var{j} may be scalars, in\n\ +which case they are expanded to all have the same length\n\ +@end enumerate\n\ +@seealso{full}\n\ +@end deftypefn") +{ + octave_value retval; + bool mutate = false; + + // WARNING: This function should always use constructions like + // retval = new octave_sparse_matrix (sm); + // To avoid calling the maybe_mutate function. This is the only + // function that should not call maybe_mutate, or at least only + // in very particular cases. + + int nargin= args.length(); + if (nargin < 1 || (nargin == 4 && !args(3).is_string ()) || nargin > 6) + { + print_usage ("sparse"); + return retval; + } + + bool use_complex = false; + bool use_bool = false; + if (nargin > 2) + { + use_complex= args(2).is_complex_type(); + use_bool = args(2).is_bool_type (); + } + else + { + use_complex= args(0).is_complex_type(); + use_bool = args(0).is_bool_type (); + } + + if (nargin == 2 && ! args(0).is_scalar_type() && args(1).is_scalar_type()) + mutate = (args(1).double_value() != 0.); + + if (nargin == 1 || (nargin == 2 && mutate)) + { + octave_value arg = args (0); + + if (is_sparse (arg)) + { + if (use_complex) + { + SparseComplexMatrix sm (((const octave_sparse_complex_matrix&) arg + .get_rep ()) + .sparse_complex_matrix_value ()); + retval = new octave_sparse_complex_matrix (sm); + } + else if (use_bool) + { + SparseBoolMatrix sm (((const octave_sparse_bool_matrix&) arg + .get_rep ()) + .sparse_bool_matrix_value ()); + retval = new octave_sparse_bool_matrix (sm); + } + else + { + SparseMatrix sm (((const octave_sparse_matrix&) arg + .get_rep ()) + .sparse_matrix_value ()); + retval = new octave_sparse_matrix (sm); + } + } + else + { + if (use_complex) + { + SparseComplexMatrix sm (args (0).complex_matrix_value ()); + if (error_state) + return retval; + retval = new octave_sparse_complex_matrix (sm); + } + else if (use_bool) + { + SparseBoolMatrix sm (args (0).bool_matrix_value ()); + if (error_state) + return retval; + retval = new octave_sparse_bool_matrix (sm); + } + else + { + SparseMatrix sm (args (0).matrix_value ()); + if (error_state) + return retval; + retval = new octave_sparse_matrix (sm); + } + } + } + else + { + int m = 1, n = 1; + if (nargin == 2) + { + m = args(0).int_value(); + n = args(1).int_value(); + if (error_state) return retval; + + if (use_complex) + retval = new octave_sparse_complex_matrix + (SparseComplexMatrix (m, n)); + else if (use_bool) + retval = new octave_sparse_bool_matrix + (SparseBoolMatrix (m, n)); + else + retval = new octave_sparse_matrix + (SparseMatrix (m, n)); + } + else + { + if (args(0).is_empty () || args (1).is_empty () + || args(2).is_empty ()) + { + if (nargin > 4) + { + m = args(3).int_value(); + n = args(4).int_value(); + } + + if (use_bool) + retval = new octave_sparse_bool_matrix + (SparseBoolMatrix (m, n)); + else + retval = new octave_sparse_matrix (SparseMatrix (m, n)); + } + else + { +// +// I use this clumsy construction so that we can use +// any orientation of args + ColumnVector ridxA = ColumnVector (args(0).vector_value + (false, true)); + ColumnVector cidxA = ColumnVector (args(1).vector_value + (false, true)); + ColumnVector coefA; + boolNDArray coefAB; + ComplexColumnVector coefAC; + bool assemble_do_sum = true; // this is the default in matlab6 + + if (use_complex) + { + if (args(2).is_empty ()) + coefAC = ComplexColumnVector (0); + else + coefAC = ComplexColumnVector + (args(2).complex_vector_value (false, true)); + } + else if (use_bool) + { + if (args(2).is_empty ()) + coefAB = boolNDArray (dim_vector (1, 0)); + else + coefAB = args(2).bool_array_value (); + dim_vector AB_dims = coefAB.dims (); + if (AB_dims.length() > 2 || (AB_dims(0) != 1 && + AB_dims(1) != 1)) + error ("sparse: vector arguments required"); + } + else + if (args(2).is_empty ()) + coefA = ColumnVector (0); + else + coefA = ColumnVector (args(2).vector_value (false, true)); + + if (error_state) + return retval; + + // Confirm that i,j,s all have the same number of elements + int ns; + if (use_complex) + ns = coefAC.length(); + else if (use_bool) + ns = coefAB.length(); + else + ns = coefA.length(); + + int ni = ridxA.length(); + int nj = cidxA.length(); + int nnz = (ni > nj ? ni : nj); + if ((ns != 1 && ns != nnz) || + (ni != 1 && ni != nnz) || + (nj != 1 && nj != nnz)) + { + error ("sparse i, j and s must have the same length"); + return retval; + } + + if (nargin == 3 || nargin == 4) + { + m = static_cast (ridxA.max()); + n = static_cast (cidxA.max()); + + // if args(3) is not string, then ignore the value + // otherwise check for summation or unique + if (nargin == 4 && args(3).is_string()) + { + std::string vv= args(3).string_value(); + if (error_state) return retval; + + if ( vv == "summation" || + vv == "sum" ) + assemble_do_sum = true; + else + if ( vv == "unique" ) + assemble_do_sum = false; + else { + error("sparse repeat flag must be 'sum' or 'unique'"); + return retval; + } + } + } + else + { + m = args(3).int_value(); + n = args(4).int_value(); + if (error_state) + return retval; + + // if args(5) is not string, then ignore the value + // otherwise check for summation or unique + if (nargin >= 6 && args(5).is_string()) + { + std::string vv= args(5).string_value(); + if (error_state) return retval; + + if ( vv == "summation" || + vv == "sum" ) + assemble_do_sum = true; + else + if ( vv == "unique" ) + assemble_do_sum = false; + else { + error("sparse repeat flag must be 'sum' or 'unique'"); + return retval; + } + } + + } + + // Convert indexing to zero-indexing used internally + ridxA -= 1.; + cidxA -= 1.; + + if (use_complex) + retval = new octave_sparse_complex_matrix + (SparseComplexMatrix (coefAC, ridxA, cidxA, m, n, + assemble_do_sum)); + else if (use_bool) + retval = new octave_sparse_bool_matrix + (SparseBoolMatrix (coefAB, ridxA, cidxA, m, n, + assemble_do_sum)); + else + retval = new octave_sparse_matrix + (SparseMatrix (coefA, ridxA, cidxA, m, n, + assemble_do_sum)); + } + } + } + + // Only called in very particular cases, not the default case + if (mutate) + retval.maybe_mutate (); + + return retval; +} + +DEFUN_DLD (full, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{FM} =} full (@var{SM})\n\ + returns a full storage matrix from a sparse one\n\ +@seealso{sparse}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length() < 1) { + print_usage ("full"); + return retval; + } + + if (args(0).class_name () == "sparse") + { + if (args(0).type_name () == "sparse matrix") + retval = args(0).matrix_value (); + else if (args(0).type_name () == "sparse complex matrix") + retval = args(0).complex_matrix_value (); + else if (args(0).type_name () == "sparse bool matrix") + retval = args(0).bool_matrix_value (); + } + else if (args(0).is_real_type()) + retval = args(0).matrix_value(); + else if (args(0).is_complex_type()) + retval = args(0).complex_matrix_value(); + else + gripe_wrong_type_arg ("full", args(0)); + + return retval; +} + +DEFUN_DLD (nnz, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{scalar} =} nnz (@var{SM})\n\ +returns number of non zero elements in SM\n\ +@seealso{sparse}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length() < 1) + { + print_usage ("nnz"); + return retval; + } + + if (args(0).class_name () == "sparse") + { + // XXX FIXME XXX should nonzero be a method of octave_base_value so that the + // below can be replaced with "retval = (double) (args(0).nonzero ());" + const octave_value& rep = args(0).get_rep (); + + if (args(0).type_name () == "sparse matrix") + retval = (double) ((const octave_sparse_matrix&) rep) .nonzero (); + else if (args(0).type_name () == "sparse complex matrix") + retval = (double) ((const octave_sparse_complex_matrix&) rep) .nonzero (); + else if (args(0).type_name () == "sparse bool matrix") + retval = (double) ((const octave_sparse_bool_matrix&) rep) .nonzero (); + } + else if (args(0).type_name () == "complex matrix") + { + const ComplexMatrix M = args(0).complex_matrix_value(); + int nnz = 0; + for( int j = 0; j < M.cols(); j++) + for( int i = 0; i < M.rows(); i++) + if (M (i, j) != 0.) + nnz++; + retval = (double) nnz; + } + else if (args(0).type_name () == "matrix") + { + const Matrix M = args(0).matrix_value(); + int nnz = 0; + for( int j = 0; j < M.cols(); j++) + for( int i = 0; i < M.rows(); i++) + if (M (i, j) != 0.) + nnz++; + retval = (double) nnz; + } + else if (args(0).type_name () == "string") + { + const charMatrix M = args(0).char_matrix_value(); + int nnz = 0; + for( int j = 0; j < M.cols(); j++) + for( int i = 0; i < M.rows(); i++) + if (M (i, j) != 0) + nnz++; + retval = (double) nnz; + } + else if (args(0).type_name () == "scalar") + retval = args(0).scalar_value() != 0.0 ? 1.0 : 0.0; + else if (args(0).type_name () == "complex scalar") + retval = args(0).complex_value() != 0.0 ? 1.0 : 0.0; + else + gripe_wrong_type_arg ("nnz", args(0)); + + return retval; +} + +DEFUN_DLD (nzmax, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{scalar} =} nzmax (@var{SM})\n\ +Returns the amount of storage allocated to the sparse matrix @var{SM}.\n\ +Note that @sc{Octave} tends to crop unused memory at the first oppurtunity\n\ +for sparse objects. There are some cases of user created sparse objects\n\ +where the value returned by @dfn{nzmaz} will not be the same as @dfn{nnz},\n\ +but in general they will give the same result.\n\ +@seealso{sparse, spalloc}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length() < 1) + { + print_usage ("nzmax"); + return retval; + } + + if (args(0).class_name () == "sparse") + { + // XXX FIXME XXX should nnz be a method of octave_base_value so that the + // below can be replaced with "retval = (double) (args(0).nz ());" + const octave_value& rep = args(0).get_rep (); + + if (args(0).type_name () == "sparse matrix") + retval = (double) ((const octave_sparse_matrix&) rep) .nnz (); + else if (args(0).type_name () == "sparse complex matrix") + retval = (double) ((const octave_sparse_complex_matrix&) rep) .nnz (); + else if (args(0).type_name () == "sparse bool matrix") + retval = (double) ((const octave_sparse_bool_matrix&) rep) .nnz (); + } + else + error ("nzmax: argument must be a sparse matrix"); + + return retval; +} + +static octave_value_list +sparse_find (const SparseMatrix& v) +{ + octave_value_list retval; + int nnz = v.nnz (); + dim_vector dv = v.dims (); + int nr = dv(0); + int nc = dv (1); + + ColumnVector I (nnz), J (nnz); + ColumnVector S (nnz); + + for (int i = 0, cx = 0; i < nc; i++) + { + OCTAVE_QUIT; + for (int j = v.cidx(i); j < v.cidx(i+1); j++ ) + { + I (cx) = static_cast (v.ridx(j) + 1); + J (cx) = static_cast (i + 1); + S (cx) = v.data(j); + cx++; + } + } + + if (dv(0) == 1) + { + retval(0)= I.transpose (); + retval(1)= J.transpose (); + retval(2)= S.transpose (); + } + else + { + retval(0)= I; + retval(1)= J; + retval(2)= S; + } + retval(3)= (double) nr; + retval(4)= (double) nc; + return retval; +} + +static octave_value_list +sparse_find (const SparseComplexMatrix& v) +{ + octave_value_list retval; + int nnz = v.nnz (); + dim_vector dv = v.dims (); + int nr = dv(0); + int nc = dv (1); + + ColumnVector I (nnz), J (nnz); + ComplexColumnVector S (nnz); + + for (int i = 0, cx = 0; i < nc; i++) + { + OCTAVE_QUIT; + for (int j = v.cidx(i); j < v.cidx(i+1); j++ ) + { + I (cx) = static_cast (v.ridx(j) + 1); + J (cx) = static_cast (i + 1); + S (cx) = v.data(j); + cx++; + } + } + + if (dv(0) == 1) + { + retval(0)= I.transpose (); + retval(1)= J.transpose (); + retval(2)= S.transpose (); + } + else + { + retval(0)= I; + retval(1)= J; + retval(2)= S; + } + retval(3)= (double) nr; + retval(4)= (double) nc; + return retval; +} + +static octave_value_list +sparse_find (const SparseBoolMatrix& v) +{ + octave_value_list retval; + int nnz = v.nnz (); + dim_vector dv = v.dims (); + int nr = dv(0); + int nc = dv (1); + + ColumnVector I (nnz), J (nnz); + ColumnVector S (nnz); + + for (int i = 0, cx = 0; i < nc; i++) + { + OCTAVE_QUIT; + for (int j = v.cidx(i); j < v.cidx(i+1); j++ ) + { + I (cx) = static_cast (v.ridx(j) + 1); + J (cx) = static_cast (i + 1); + S (cx) = static_cast (v.data(j)); + cx++; + } + } + + if (dv(0) == 1) + { + retval(0)= I.transpose (); + retval(1)= J.transpose (); + retval(2)= S.transpose (); + } + else + { + retval(0)= I; + retval(1)= J; + retval(2)= S; + } + retval(3)= (double) nr; + retval(4)= (double) nc; + return retval; +} + +// PKG_ADD: dispatch ("find", "spfind", "sparse matrix") +// PKG_ADD: dispatch ("find", "spfind", "sparse complex matrix") +// PKG_ADD: dispatch ("find", "spfind", "sparse bool matrix") +DEFUN_DLD (spfind, args, nargout , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[...] =} spfind (...)\n\ +SPFIND: a sparse version of the find operator\n\ +@enumerate\n\ + @item\n\ +@var{x }= spfind( @var{a })\n\ + @itemize @w\n\ +is analagous to @var{x}= find(@var{A}(:))@*\n\ +where @var{A}= full(@var{a})\n\ + @end itemize\n\ + @item\n\ +[@var{i},@var{j},@var{v},@var{nr},@var{nc}] = spfind( @var{a} )\n\ + @itemize @w\n\ +returns column vectors @var{i},@var{j},@var{v} such that@*\n\ +@var{a}= sparse(@var{i},@var{j},@var{v},@var{nr},@var{nc})\n\ + @end itemize\n\ +@end enumerate\n\ +@seealso{sparse}\n\ +@end deftypefn") +{ + octave_value_list retval; + int nargin = args.length (); + + if (nargin != 1) + { + print_usage ("spfind"); + return retval; + } + + + octave_value arg = args(0); + + if (arg.class_name () == "sparse") + { + if (arg.type_name () == "sparse matrix") + retval = sparse_find (args(0).sparse_matrix_value ()); + else if (arg.type_name () == "sparse complex matrix" ) + retval = sparse_find (args(0).sparse_complex_matrix_value ()); + else if (arg.type_name () == "sparse bool matrix" ) + retval = sparse_find (args(0).sparse_bool_matrix_value ()); + else + gripe_wrong_type_arg ("spfind", arg); + } + else + gripe_wrong_type_arg ("spfind", arg); + + if (nargout == 1 || nargout ==0 ) + { + // only find location as fortran index + octave_value_list tmp; + tmp(0) = retval(0) + (retval(1)-1)*retval(3); + retval = tmp; + } + + return retval; +} + +#define SPARSE_DIM_ARG_BODY(NAME, FUNC) \ + int nargin = args.length(); \ + octave_value retval; \ + if ((nargin != 1 ) && (nargin != 2)) \ + print_usage (#NAME); \ + else { \ + int dim = (nargin == 1 ? -1 : args(1).int_value(true) - 1); \ + if (error_state) return retval; \ + if (dim < -1 || dim > 1) { \ + error (#NAME ": invalid dimension argument = %d", dim + 1); \ + return retval; \ + } \ + if (args(0).type_id () == \ + octave_sparse_matrix::static_type_id () || args(0).type_id () == \ + octave_sparse_bool_matrix::static_type_id ()) { \ + retval = args(0).sparse_matrix_value () .FUNC (dim); \ + } else if (args(0).type_id () == \ + octave_sparse_complex_matrix::static_type_id ()) { \ + retval = args(0).sparse_complex_matrix_value () .FUNC (dim); \ + } else \ + print_usage (#NAME); \ + } \ + return retval + +// PKG_ADD: dispatch ("prod", "spprod", "sparse matrix"); +// PKG_ADD: dispatch ("prod", "spprod", "sparse complex matrix"); +// PKG_ADD: dispatch ("prod", "spprod", "sparse bool matrix"); +DEFUN_DLD (spprod, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} spprod (@var{x},@var{dim})\n\ +Product of elements along dimension @var{dim}. If @var{dim} is omitted,\n\ +it defaults to 1 (column-wise products).\n\ +@end deftypefn\n\ +@seealso{spsum, spsumsq}") +{ + SPARSE_DIM_ARG_BODY (spprod, prod); +} + +// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse matrix"); +// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse complex matrix"); +// PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse bool matrix"); +DEFUN_DLD (spcumprod, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} spcumprod (@var{x},@var{dim})\n\ +Cumulative product of elements along dimension @var{dim}. If @var{dim}\n\ +is omitted, it defaults to 1 (column-wise cumulative products).\n\ +@end deftypefn\n\ +@seealso{spcumsum}") +{ + SPARSE_DIM_ARG_BODY (spcumprod, cumprod); +} + +// PKG_ADD: dispatch ("sum", "spsum", "sparse matrix"); +// PKG_ADD: dispatch ("sum", "spsum", "sparse complex matrix"); +// PKG_ADD: dispatch ("sum", "spsum", "sparse bool matrix"); +DEFUN_DLD (spsum, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} spsum (@var{x},@var{dim})\n\ +Sum of elements along dimension @var{dim}. If @var{dim} is omitted, it\n\ +defaults to 1 (column-wise sum).\n\ +@end deftypefn\n\ +@seealso{spprod, spsumsq}") +{ + SPARSE_DIM_ARG_BODY (spsum, sum); +} + +// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse matrix"); +// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse complex matrix"); +// PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse bool matrix"); +DEFUN_DLD (spcumsum, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} spcumsum (@var{x},@var{dim})\n\ +Cumulative sum of elements along dimension @var{dim}. If @var{dim}\n\ +is omitted, it defaults to 1 (column-wise cumulative sums).\n\ +@end deftypefn\n\ +@seealso{spcumprod}") +{ + SPARSE_DIM_ARG_BODY (spcumsum, cumsum); +} + +// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse matrix"); +// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse complex matrix"); +// PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse bool matrix"); +DEFUN_DLD (spsumsq, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} spsumsq (@var{x},@var{dim})\n\ +Sum of squares of elements along dimension @var{dim}. If @var{dim}\n\ +is omitted, it defaults to 1 (column-wise sum of squares).\n\ +This function is equivalent to computing\n\ +@example\n\ +spsum (x .* spconj (x), dim)\n\ +@end example\n\ +but it uses less memory and avoids calling @code{spconj} if @var{x} is\n\ +real.\n\ +@end deftypefn\n\ +@seealso{spprod, spsum}") +{ + SPARSE_DIM_ARG_BODY (spsumsq, sumsq); +} + +#define MINMAX_BODY(FCN) \ + \ + octave_value_list retval; \ + \ + int nargin = args.length (); \ + \ + if (nargin < 1 || nargin > 3 || nargout > 2) \ + { \ + print_usage (#FCN); \ + return retval; \ + } \ + \ + octave_value arg1; \ + octave_value arg2; \ + octave_value arg3; \ + \ + switch (nargin) \ + { \ + case 3: \ + arg3 = args(2); \ + \ + case 2: \ + arg2 = args(1); \ + \ + case 1: \ + arg1 = args(0); \ + break; \ + \ + default: \ + panic_impossible (); \ + break; \ + } \ + \ + int dim; \ + dim_vector dv = ((const octave_sparse_matrix&) arg1) .dims (); \ + if (error_state) \ + { \ + gripe_wrong_type_arg (#FCN, arg1); \ + return retval; \ + } \ + \ + if (nargin == 3) \ + { \ + dim = arg3.nint_value () - 1; \ + if (dim < 0 || dim >= dv.length ()) \ + { \ + error ("%s: invalid dimension", #FCN); \ + return retval; \ + } \ + } \ + else \ + { \ + dim = 0; \ + while ((dim < dv.length ()) && (dv (dim) <= 1)) \ + dim++; \ + if (dim == dv.length ()) \ + dim = 0; \ + } \ + \ + bool single_arg = (nargin == 1) || arg2.is_empty(); \ + \ + if (single_arg && (nargout == 1 || nargout == 0)) \ + { \ + if (arg1.type_id () == octave_sparse_matrix::static_type_id ()) \ + retval(0) = arg1.sparse_matrix_value () .FCN (dim); \ + else if (arg1.type_id () == \ + octave_sparse_complex_matrix::static_type_id ()) \ + retval(0) = arg1.sparse_complex_matrix_value () .FCN (dim); \ + else \ + gripe_wrong_type_arg (#FCN, arg1); \ + } \ + else if (single_arg && nargout == 2) \ + { \ + Array2 index; \ + \ + if (arg1.type_id () == octave_sparse_matrix::static_type_id ()) \ + retval(0) = arg1.sparse_matrix_value () .FCN (index, dim); \ + else if (arg1.type_id () == \ + octave_sparse_complex_matrix::static_type_id ()) \ + retval(0) = arg1.sparse_complex_matrix_value () .FCN (index, dim); \ + else \ + gripe_wrong_type_arg (#FCN, arg1); \ + \ + int len = index.numel (); \ + \ + if (len > 0) \ + { \ + double nan_val = lo_ieee_nan_value (); \ + \ + NDArray idx (index.dims ()); \ + \ + for (int i = 0; i < len; i++) \ + { \ + OCTAVE_QUIT; \ + int tmp = index.elem (i) + 1; \ + idx.elem (i) = (tmp <= 0) \ + ? nan_val : static_cast (tmp); \ + } \ + \ + retval(1) = idx; \ + } \ + else \ + retval(1) = NDArray (); \ + } \ + else \ + { \ + int arg1_is_scalar = arg1.is_scalar_type (); \ + int arg2_is_scalar = arg2.is_scalar_type (); \ + \ + int arg1_is_complex = arg1.is_complex_type (); \ + int arg2_is_complex = arg2.is_complex_type (); \ + \ + if (arg1_is_scalar) \ + { \ + if (arg1_is_complex || arg2_is_complex) \ + { \ + Complex c1 = arg1.complex_value (); \ + \ + SparseComplexMatrix m2 = arg2.sparse_complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseComplexMatrix result = FCN (c1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else \ + { \ + double d1 = arg1.double_value (); \ + SparseMatrix m2 = arg2.sparse_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseMatrix result = FCN (d1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else if (arg2_is_scalar) \ + { \ + if (arg1_is_complex || arg2_is_complex) \ + { \ + SparseComplexMatrix m1 = arg1.sparse_complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + Complex c2 = arg2.complex_value (); \ + SparseComplexMatrix result = FCN (m1, c2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + else \ + { \ + SparseMatrix m1 = arg1.sparse_matrix_value (); \ + \ + if (! error_state) \ + { \ + double d2 = arg2.double_value (); \ + SparseMatrix result = FCN (m1, d2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else \ + { \ + if (arg1_is_complex || arg2_is_complex) \ + { \ + SparseComplexMatrix m1 = arg1.sparse_complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseComplexMatrix m2 = arg2.sparse_complex_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseComplexMatrix result = FCN (m1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + else \ + { \ + SparseMatrix m1 = arg1.sparse_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseMatrix m2 = arg2.sparse_matrix_value (); \ + \ + if (! error_state) \ + { \ + SparseMatrix result = FCN (m1, m2); \ + if (! error_state) \ + retval(0) = result; \ + } \ + } \ + } \ + } \ + } \ + \ + return retval + +// PKG_ADD: dispatch ("min", "spmin", "sparse matrix"); +// PKG_ADD: dispatch ("min", "spmin", "sparse complex matrix"); +// PKG_ADD: dispatch ("min", "spmin", "sparse bool matrix"); +DEFUN_DLD (spmin, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Mapping Function} {} spmin (@var{x}, @var{y}, @var{dim})\n\ +@deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmin (@var{x})\n\ +@cindex Utility Functions\n\ +For a vector argument, return the minimum value. For a matrix\n\ +argument, return the minimum value from each column, as a row\n\ +vector, or over the dimension @var{dim} if defined. For two matrices\n\ +(or a matrix and scalar), return the pair-wise minimum.\n\ +Thus,\n\ +\n\ +@example\n\ +min (min (@var{x}))\n\ +@end example\n\ +\n\ +@noindent\n\ +returns the smallest element of @var{x}, and\n\ +\n\ +@example\n\ +@group\n\ +min (2:5, pi)\n\ + @result{} 2.0000 3.0000 3.1416 3.1416\n\ +@end group\n\ +@end example\n\ +@noindent\n\ +compares each element of the range @code{2:5} with @code{pi}, and\n\ +returns a row vector of the minimum values.\n\ +\n\ +For complex arguments, the magnitude of the elements are used for\n\ +comparison.\n\ +\n\ +If called with one input and two output arguments,\n\ +@code{min} also returns the first index of the\n\ +minimum value(s). Thus,\n\ +\n\ +@example\n\ +@group\n\ +[x, ix] = min ([1, 3, 0, 2, 5])\n\ + @result{} x = 0\n\ + ix = 3\n\ +@end group\n\ +@end example\n\ +@end deftypefn") +{ + MINMAX_BODY (min); +} + +// PKG_ADD: dispatch ("max", "spmax", "sparse matrix"); +// PKG_ADD: dispatch ("max", "spmax", "sparse complex matrix"); +// PKG_ADD: dispatch ("max", "spmax", "sparse bool matrix"); +DEFUN_DLD (spmax, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Mapping Function} {} spmax (@var{x}, @var{y}, @var{dim})\n\ +@deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmax (@var{x})\n\ +@cindex Utility Functions\n\ +For a vector argument, return the maximum value. For a matrix\n\ +argument, return the maximum value from each column, as a row\n\ +vector, or over the dimension @var{dim} if defined. For two matrices\n\ +(or a matrix and scalar), return the pair-wise maximum.\n\ +Thus,\n\ +\n\ +@example\n\ +max (max (@var{x}))\n\ +@end example\n\ +\n\ +@noindent\n\ +returns the largest element of @var{x}, and\n\ +\n\ +@example\n\ +@group\n\ +max (2:5, pi)\n\ + @result{} 3.1416 3.1416 4.0000 5.0000\n\ +@end group\n\ +@end example\n\ +@noindent\n\ +compares each element of the range @code{2:5} with @code{pi}, and\n\ +returns a row vector of the maximum values.\n\ +\n\ +For complex arguments, the magnitude of the elements are used for\n\ +comparison.\n\ +\n\ +If called with one input and two output arguments,\n\ +@code{max} also returns the first index of the\n\ +maximum value(s). Thus,\n\ +\n\ +@example\n\ +@group\n\ +[x, ix] = max ([1, 3, 5, 2, 5])\n\ + @result{} x = 5\n\ + ix = 3\n\ +@end group\n\ +@end example\n\ +@end deftypefn") +{ + MINMAX_BODY (max); +} + +// PKG_ADD: dispatch ("atan2", "spatan2", "sparse matrix"); +// PKG_ADD: dispatch ("atan2", "spatan2", "sparse complex matrix"); +// PKG_ADD: dispatch ("atan2", "spatan2", "sparse bool matrix"); +DEFUN_DLD (spatan2, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} spatan2 (@var{y}, @var{x})\n\ +Compute atan (Y / X) for corresponding sparse matrix elements of Y and X.\n\ +The result is in range -pi to pi.\n\ +@end deftypefn\n") +{ + octave_value retval; + int nargin = args.length (); + if (nargin == 2) { + SparseMatrix a, b; + double da, db; + bool is_double_a = false; + bool is_double_b = false; + + if (args(0).is_scalar_type ()) + { + is_double_a = true; + da = args(0).double_value(); + } + else + a = args(0).sparse_matrix_value (); + + if (args(1).is_scalar_type ()) + { + is_double_b = true; + db = args(1).double_value(); + } + else + b = args(1).sparse_matrix_value (); + + if (is_double_a && is_double_b) + retval = Matrix (1, 1, atan2(da, db)); + else if (is_double_a) + retval = atan2 (da, b); + else if (is_double_b) + retval = atan2 (a, db); + else + retval = atan2 (a, b); + + } else + print_usage("spatan2"); + + return retval; +} + +static octave_value +make_spdiag (const octave_value& a, const octave_value& b) +{ + octave_value retval; + + if (a.is_complex_type ()) + { + SparseComplexMatrix m = a.sparse_complex_matrix_value (); + int k = b.nint_value(true); + + if (error_state) + return retval; + + int nr = m.rows (); + int nc = m.columns (); + + if (nr == 0 || nc == 0) + retval = m; + else if (nr == 1 || nc == 1) + { + int roff = 0; + int coff = 0; + if (k > 0) + { + roff = 0; + coff = k; + } + else if (k < 0) + { + k = -k; + roff = k; + coff = 0; + } + + if (nr == 1) + { + int n = nc + k; + int nz = m.nnz (); + SparseComplexMatrix r (n, n, nz); + for (int i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + r.xdata (i) = m.data (i); + r.xridx (i) = j + roff; + } + r.xcidx (j+coff+1) = m.cidx(j+1); + } + for (int i = nc+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + else + { + int n = nr + k; + int nz = m.nnz (); + int ii = 0; + int ir = m.ridx(0); + SparseComplexMatrix r (n, n, nz); + for (int i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (int i = 0; i < nr; i++) + { + if (ir == i) + { + r.xdata (ii) = m.data (ii); + r.xridx (ii++) = ir + roff; + if (ii != nz) + ir = m.ridx (ii); + } + r.xcidx (i+coff+1) = ii; + } + for (int i = nr+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + } + else + { + SparseComplexMatrix r = m.diag (k); + // Don't use numel, since it can overflow for very large matrices + if (r.rows () > 0 && r.cols () > 0) + retval = r; + } + } + else if (a.is_real_type ()) + { + SparseMatrix m = a.sparse_matrix_value (); + + int k = b.nint_value(true); + + if (error_state) + return retval; + + int nr = m.rows (); + int nc = m.columns (); + + if (nr == 0 || nc == 0) + retval = m; + else if (nr == 1 || nc == 1) + { + int roff = 0; + int coff = 0; + if (k > 0) + { + roff = 0; + coff = k; + } + else if (k < 0) + { + k = -k; + roff = k; + coff = 0; + } + + if (nr == 1) + { + int n = nc + k; + int nz = m.nnz (); + SparseMatrix r (n, n, nz); + + for (int i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = m.cidx(j); i < m.cidx(j+1); i++) + { + r.xdata (i) = m.data (i); + r.xridx (i) = j + roff; + } + r.xcidx (j+coff+1) = m.cidx(j+1); + } + for (int i = nc+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + else + { + int n = nr + k; + int nz = m.nnz (); + int ii = 0; + int ir = m.ridx(0); + SparseMatrix r (n, n, nz); + for (int i = 0; i < coff+1; i++) + r.xcidx (i) = 0; + for (int i = 0; i < nr; i++) + { + if (ir == i) + { + r.xdata (ii) = m.data (ii); + r.xridx (ii++) = ir + roff; + if (ii != nz) + ir = m.ridx (ii); + } + r.xcidx (i+coff+1) = ii; + } + for (int i = nr+coff+1; i < n+1; i++) + r.xcidx (i) = nz; + retval = r; + } + } + else + { + SparseMatrix r = m.diag (k); + if (r.rows () > 0 && r.cols () > 0) + retval = r; + } + } + else + gripe_wrong_type_arg ("spdiag", a); + + return retval; +} + +// PKG_ADD: dispatch ("diag", "spdiag", "sparse matrix"); +// PKG_ADD: dispatch ("diag", "spdiag", "sparse complex matrix"); +// PKG_ADD: dispatch ("diag", "spdiag", "sparse bool matrix"); +DEFUN_DLD (spdiag, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} spdiag (@var{v}, @var{k})\n\ +Return a diagonal matrix with the sparse vector @var{v} on diagonal\n\ +@var{k}. The second argument is optional. If it is positive, the vector is\n\ +placed on the @var{k}-th super-diagonal. If it is negative, it is placed\n\ +on the @var{-k}-th sub-diagonal. The default value of @var{k} is 0, and\n\ +the vector is placed on the main diagonal. For example,\n\ +\n\ +@example\n\ +spdiag ([1, 2, 3], 1)\n\ +ans =\n\ +\n\ +Compressed Column Sparse (rows=4, cols=4, nnz=3)\n\ + (1 , 2) -> 1\n\ + (2 , 3) -> 2\n\ + (3 , 4) -> 3\n\ +@end example\n\ +\n\ +@end deftypefn\n\ +@seealso{diag}") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1 && args(0).is_defined ()) + retval = make_spdiag (args(0), octave_value(0.)); + else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) + retval = make_spdiag (args(0), args(1)); + else + print_usage ("spdiag"); + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/DLD-FUNCTIONS/spdet.cc b/src/DLD-FUNCTIONS/spdet.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/spdet.cc @@ -0,0 +1,130 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun-dld.h" +#include "error.h" +#include "gripes.h" +#include "oct-obj.h" +#include "utils.h" + +#include "dbleDET.h" +#include "CmplxDET.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// PKG_ADD: dispatch ("det", "spdet", "sparse matrix") +// PKG_ADD: dispatch ("det", "spdet", "sparse complex matrix") +// PKG_ADD: dispatch ("det", "spdet", "sparse bool matrix") +DEFUN_DLD (spdet, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{d}, @var{rcond}] = } spdet (@var{a})\n\ +Compute the determinant of sparse matrix @var{a} using UMFPACK. Return\n\ +an estimate of the reciprocal condition number if requested.\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin != 1) + { + print_usage ("spdet"); + return retval; + } + + octave_value arg = args(0); + + int nr = arg.rows (); + int nc = arg.columns (); + + if (nr == 0 && nc == 0) + { + retval(0) = 1.0; + return retval; + } + + int arg_is_empty = empty_arg ("spdet", nr, nc); + if (arg_is_empty < 0) + return retval; + if (arg_is_empty > 0) + return octave_value (Matrix (1, 1, 1.0)); + + if (nr != nc) + { + gripe_square_matrix_required ("spdet"); + return retval; + } + + if (arg.is_real_type ()) + { + SparseMatrix m = args(0).sparse_matrix_value (); + + if (! error_state) + { + // Always compute rcond, so we can detect numerically + // singular matrices. + + int info; + double rcond = 0.0; + DET det = m.determinant (info, rcond); + retval(1) = rcond; + volatile double xrcond = rcond; + xrcond += 1.0; + retval(0) = ((info == -1 || xrcond == 1.0) ? 0.0 : det.value ()); + } + } + else if (arg.is_complex_type ()) + { + SparseComplexMatrix m = args(0).sparse_complex_matrix_value (); + + if (! error_state) + { + // Always compute rcond, so we can detect numerically + // singular matrices. + + int info; + double rcond = 0.0; + ComplexDET det = m.determinant (info, rcond); + retval(1) = rcond; + volatile double xrcond = rcond; + xrcond += 1.0; + retval(0) = ((info == -1 || xrcond == 1.0) + ? Complex (0.0) : det.value ()); + } + } + else + { + gripe_wrong_type_arg ("spdet", arg); + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/DLD-FUNCTIONS/splu.cc b/src/DLD-FUNCTIONS/splu.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/splu.cc @@ -0,0 +1,400 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun-dld.h" +#include "error.h" +#include "gripes.h" +#include "oct-obj.h" +#include "utils.h" + +#include "SparseCmplxLU.h" +#include "SparsedbleLU.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// PKG_ADD: dispatch ("lu", "splu", "sparse matrix") +// PKG_ADD: dispatch ("lu", "splu", "sparse complex matrix") +// PKG_ADD: dispatch ("lu", "splu", "sparse bool matrix") +DEFUN_DLD (splu, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{l}, @var{u}] =} splu (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@dots{}, @var{thres})\n\ +@deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@dots{}, @var{Q})\n\ +@cindex LU decomposition\n\ +Compute the LU decomposition of the sparse matrix @var{a}, using\n\ +subroutines from UMFPACK. The result is returned in a permuted\n\ +form, according to the optional return values @var{P} and @var{Q}.\n\ +\n\ +Called with two or three output arguments and a single input argument,\n\ +@dfn{splu} is a replacement for @dfn{lu}, and therefore the sparsity\n\ +preserving column permutations @var{Q} are not performed. Called with\n\ +a fourth output argument, the sparsity preserving column transformation\n\ +@var{Q} is returned, such that @code{@var{P} * @var{a} * @var{Q} =\n\ +@var{l} * @var{u}}.\n\ +\n\ +An additional input argument @var{thres}, that defines the pivoting\n\ +threshold can be given. Alternatively, the desired sparsity preserving\n\ +column permutations @var{Q} can be passed. Note that @var{Q} is assumed\n\ +to be fixed if three are fewer than four output arguments. Otherwise,\n\ +the updated column permutations are returned as the fourth argument.\n\ +\n\ +With two output arguments, returns the permuted forms of the upper and\n\ +lower triangular matrices, such that @code{@var{a} = @var{l} * @var{u}}.\n\ +With two or three output arguments, if a user-defined @var{Q} is given,\n\ +then @code{@var{u} * @var{Q}'} is returned. The matrix is not required to\n\ +be square.\n\ +@end deftypefn\n\ +@seealso{sparse, spinv, colamd, symamd}") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin < 1 || nargin > 3 || nargout > 4) + { + print_usage ("splu"); + return retval; + } + + octave_value arg = args(0); + + int nr = arg.rows (); + int nc = arg.columns (); + + int arg_is_empty = empty_arg ("splu", nr, nc); + + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + return octave_value_list (3, SparseMatrix ()); + + ColumnVector Qinit; + bool have_Qinit = false; + double thres = -1.; + + for (int k = 1; k < nargin; k++) + { + if (args(k).class_name () == "sparse") + { + SparseMatrix tmp = args (k).sparse_matrix_value (); + + if (error_state) + { + error ("splu: Not a valid permutation/threshold"); + return retval; + } + + dim_vector dv = tmp.dims (); + + if (dv(0) == 1 && dv(1) == 1) + thres = tmp (0); + else if (dv(0) == 1 || dv(1) == 1) + { + int nel = tmp.numel (); + Qinit.resize (nel); + for (int i = 0; i < nel; i++) + Qinit (i) = tmp (i) - 1; + have_Qinit = true; + } + else + { + int t_nc = tmp.cols (); + + if (tmp.nnz () != t_nc) + error ("splu: Not a valid permutation matrix"); + else + { + for (int i = 0; i < t_nc + 1; i++) + if (tmp.cidx(i) != i) + { + error ("splu: Not a valid permutation matrix"); + break; + } + } + + if (!error_state) + { + for (int i = 0; i < t_nc; i++) + if (tmp.data (i) != 1.) + { + error ("splu: Not a valid permutation matrix"); + break; + } + else + Qinit (i) = tmp.ridx (i) - 1; + } + + if (! error_state) + have_Qinit = true; + } + } + else + { + NDArray tmp = args(k).array_value (); + + if (error_state) + return retval; + + dim_vector dv = tmp.dims (); + if (dv.length () > 2) + { + error ("splu: second argument must be a vector/matrix or a scalar"); + } + else if (dv(0) == 1 && dv(1) == 1) + thres = tmp (0); + else if (dv(0) == 1 || dv(1) == 1) + { + int nel = tmp.numel (); + Qinit.resize (nel); + for (int i = 0; i < nel; i++) + Qinit (i) = tmp (i) - 1; + have_Qinit = true; + } + else + { + SparseMatrix tmp2 (tmp); + + int t_nc = tmp2.cols (); + + if (tmp2.nnz () != t_nc) + error ("splu: Not a valid permutation matrix"); + else + { + for (int i = 0; i < t_nc + 1; i++) + if (tmp2.cidx(i) != i) + { + error ("splu: Not a valid permutation matrix"); + break; + } + } + + if (!error_state) + { + for (int i = 0; i < t_nc; i++) + if (tmp2.data (i) != 1.) + { + error ("splu: Not a valid permutation matrix"); + break; + } + else + Qinit (i) = tmp2.ridx (i) - 1; + } + + if (! error_state) + have_Qinit = true; + } + } + } + + if (error_state) + return retval; + + if (arg.is_real_type ()) + { + SparseMatrix m = arg.sparse_matrix_value (); + + if (nargout < 4 && ! have_Qinit) + { + int m_nc = m.cols (); + Qinit.resize (m_nc); + for (int i = 0; i < m_nc; i++) + Qinit (i) = i; + } + + if (! error_state) + { + switch (nargout) + { + case 0: + case 1: + case 2: + { + SparseLU fact (m, Qinit, thres, true); + + SparseMatrix P = fact.Pr (); + SparseMatrix L = P.transpose () * fact.L (); + if (have_Qinit) + retval(1) = fact.U () * fact.Pc ().transpose (); + else + retval(1) = fact.U (); + + retval(0) = L; + } + break; + + case 3: + { + SparseLU fact (m, Qinit, thres, true); + + retval(2) = fact.Pr (); + if (have_Qinit) + retval(1) = fact.U () * fact.Pc ().transpose (); + else + retval(1) = fact.U (); + retval(0) = fact.L (); + } + break; + + case 4: + default: + { + if (have_Qinit) + { + SparseLU fact (m, Qinit, thres, false); + + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + else + { + SparseLU fact (m, thres); + + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + } + break; + } + } + } + else if (arg.is_complex_type ()) + { + SparseComplexMatrix m = arg.sparse_complex_matrix_value (); + + if (nargout < 4 && ! have_Qinit) + { + int m_nc = m.cols (); + Qinit.resize (m_nc); + for (int i = 0; i < m_nc; i++) + Qinit (i) = i; + } + + if (! error_state) + { + switch (nargout) + { + case 0: + case 1: + case 2: + { + SparseComplexLU fact (m, Qinit, thres, true); + + SparseMatrix P = fact.Pr (); + SparseComplexMatrix L = P.transpose () * fact.L (); + + if (have_Qinit) + retval(1) = fact.U () * fact.Pc ().transpose (); + else + retval(1) = fact.U (); + retval(0) = L; + } + break; + + case 3: + { + SparseComplexLU fact (m, Qinit, thres, true); + + retval(2) = fact.Pr (); + if (have_Qinit) + retval(1) = fact.U () * fact.Pc ().transpose (); + else + retval(1) = fact.U (); + retval(0) = fact.L (); + } + break; + + case 4: + default: + { + if (have_Qinit) + { + SparseComplexLU fact (m, Qinit, thres, false); + + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + else + { + SparseComplexLU fact (m, thres); + + retval(3) = fact.Pc (); + retval(2) = fact.Pr (); + retval(1) = fact.U (); + retval(0) = fact.L (); + } + } + break; + } + } + } + else + { + gripe_wrong_type_arg ("splu", arg); + } + + return retval; +} + +// PKG_ADD: dispatch ("inv", "spinv", "sparse matrix") +// PKG_ADD: dispatch ("inv", "spinv", "sparse complex matrix") +// PKG_ADD: dispatch ("inv", "spinv", "sparse bool matrix") +// PKG_ADD: dispatch ("inverse", "spinv", "sparse matrix") +// PKG_ADD: dispatch ("inverse", "spinv", "sparse complex matrix") +// PKG_ADD: dispatch ("inverse", "spinv", "sparse bool matrix") +DEFUN_DLD (spinv, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{x}, @var{rcond}] = } spinv (@var{a}, @var{Q})\n\ +@deftypefnx {Loadable Function} {[@var{x}, @var{rcond}, @var{Q}] = } spinv (@var{a}, @var{Q})\n\ +Compute the inverse of the square matrix @var{a}. Return an estimate\n\ +of the reciprocal condition number if requested, otherwise warn of an\n\ +ill-conditioned matrix if the reciprocal condition number is small.\n\ +\n\ +An optional second input argument @var{Q} is the optional pre-ordering of\n\ +the matrix, such that @code{@var{x} = inv (@var{a} (:, @var{Q}))}. @var{Q}\n\ +can equally be a matrix, in which case @code{@var{x} = inv (@var{a} *\n\ +@var{Q}))}.\n\ +\n\ +If a third output argument is given then the permuations to achieve a sparse\n\ +inverse are returned. It is not required that the return column permutations\n\ +@var{Q} and the same as the user supplied permutations\n\ +@end deftypefn") +{ + error ("spinv: not implemented yet"); + return octave_value (); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/DLD-FUNCTIONS/spparms.cc b/src/DLD-FUNCTIONS/spparms.cc new file mode 100644 --- /dev/null +++ b/src/DLD-FUNCTIONS/spparms.cc @@ -0,0 +1,167 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun-dld.h" +#include "ov.h" +#include "pager.h" +#include "error.h" +#include "gripes.h" + +#include "oct-spparms.h" + +DEFUN_DLD (spparms, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} { } spparms ()\n\ +@deftypefnx {Loadable Function} {@var{vals} =} spparms ()\n\ +@deftypefnx {Loadable Function} {[@var{keys}, @var{vals}] =} spparms ()\n\ +@deftypefnx {Loadable Function} {@var{val} =} spparms (@var{key})\n\ +@deftypefnx {Loadable Function} { } spparms (@var{vals})\n\ +@deftypefnx {Loadable Function} { } spparms ('defaults')\n\ +@deftypefnx {Loadable Function} { } spparms ('tight')\n\ +@deftypefnx {Loadable Function} { } spparms (@var{key}, @var{val})\n\ +Sets or displays the parameters used by the sparse solvers and factorization\n\ +functions. The first four calls above get information about the current\n\ +settings, while the others change the current settings. The parameters are\n\ +stored as pairs of keys and values, where the values are all floats and the\n\ +keys are one of the strings\n\ +\n\ +@itemize\n\ +@item spumoni\n\ +Printing level of debugging information of the solvers (default 0)\n\ +@item ths_rel\n\ +?? (default 1)\n\ +@item ths_abs\n\ +?? (default 1)\n\ +@item exact_d\n\ +?? (default 0)\n\ +@item supernd\n\ +?? (default 3)\n\ +@item rreduce\n\ +?? (default 3)\n\ +@item wh_frac\n\ +?? (default 0.5)\n\ +@item autommd\n\ +Flag whether the LU/QR and the '\\' and '/' operators will automatically\n\ +use the sparsity preserving mmd functions (default 1)\n\ +@item autoamd\n\ +Flag whether the LU and the '\\' and '/' operators will automatically\n\ +use the sparsity preserving amd functions (default 1)\n\ +@item piv_tol\n\ +The pivot tolerance of the UMFPACK solvers (default 0.1)\n\ +@item bandden\n\ +?? (default 0.5)\n\ +@item umfpack\n\ +Flag whether the UMFPACK or mmd solvers are used for the LU, '\\' and\n\ +'/' operations (default 1)\n\ +@end itemize\n\ +\n\ +The value of individual keys can be set with @code{spparms (@var{key},\n\ +@var{val})}. The default values can be restored with the special keyword\n\ +'defaults'. The special keyword 'tight' can be used to set the mmd solvers\n\ +to attempt for a sparser solution at the potetial cost of longer running\n\ +time.\n\ +@end deftypefn") +{ + octave_value_list retval; + int nargin = args.length (); + + if (nargin == 0) + { + if (nargout == 0) + Voctave_sparse_controls.print_info (octave_stdout, ""); + else if (nargout == 1) + retval(0) = Voctave_sparse_controls.get_vals (); + else if (nargout == 2) + { + retval (0) = Voctave_sparse_controls.get_keys (); + retval (1) = Voctave_sparse_controls.get_vals (); + } + else + error ("spparms: too many outpu arguments"); + } + else if (nargin == 1) + { + if (args(0).is_string ()) + { + std::string str = args(0).string_value (); + int len = str.length (); + for (int i = 0; i < len; i++) + str [i] = tolower (str [i]); + + if (str == "defaults") + Voctave_sparse_controls.defaults (); + else if (str == "tight") + Voctave_sparse_controls.tight (); + else + { + double val = Voctave_sparse_controls.get_key (str); + if (xisnan (val)) + error ("spparams: unrecognized key"); + else + retval (0) = val; + } + } + else + { + NDArray vals = args(0).array_value (); + + if (error_state) + error ("spparms: input must be a string or a vector"); + else if (vals.numel () > OCTAVE_SPARSE_CONTROLS_SIZE) + error ("spparams: too many elements in values vector"); + else + for (int i = 0; i < vals.length (); i++) + Voctave_sparse_controls (i) = vals (i); + } + } + else if (nargin == 2) + { + if (args(0).is_string ()) + { + std::string str = args(0).string_value (); + + double val = args(1).double_value (); + + if (error_state) + error ("spparms: second argument must be a real scalar"); + else if (str == "umfpack") + warning ("spparms: request to disable umfpack solvers ignored"); + else if (!Voctave_sparse_controls.set_key (str, val)) + error ("spparms: key not found"); + } + else + error ("spparms: first argument must be a string"); + } + else + error ("spparms: too many input arguments"); + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/Makefile.in b/src/Makefile.in --- a/src/Makefile.in +++ b/src/Makefile.in @@ -42,13 +42,14 @@ OPT_HANDLERS := DASPK-opts.cc DASRT-opts.cc DASSL-opts.cc \ LSODE-opts.cc NLEqn-opts.cc ODESSA-opts.cc Quad-opts.cc -DLD_XSRC := balance.cc besselj.cc betainc.cc chol.cc colloc.cc \ - daspk.cc dasrt.cc dassl.cc det.cc eig.cc expm.cc fft.cc fft2.cc \ - fftn.cc fftw_wisdom.cc filter.cc find.cc fsolve.cc gammainc.cc \ - gcd.cc getgrent.cc getpwent.cc getrusage.cc givens.cc hess.cc \ - inv.cc kron.cc lpsolve.cc lsode.cc lu.cc minmax.cc \ - odessa.cc pinv.cc qr.cc quad.cc qz.cc rand.cc schur.cc \ - sort.cc sqrtm.cc svd.cc syl.cc time.cc gplot.l +DLD_XSRC := balance.cc besselj.cc betainc.cc chol.cc colamd.cc \ + colloc.cc daspk.cc dasrt.cc dassl.cc det.cc dispatch.cc \ + eig.cc expm.cc fft.cc fft2.cc fftn.cc fftw_wisdom.cc \ + filter.cc find.cc fsolve.cc gammainc.cc gcd.cc getgrent.cc \ + getpwent.cc getrusage.cc givens.cc hess.cc inv.cc kron.cc \ + lpsolve.cc lsode.cc lu.cc minmax.cc odessa.cc pinv.cc qr.cc \ + quad.cc qz.cc rand.cc schur.cc sort.cc sparse.cc spdet.cc \ + splu.cc spparms.cc sqrtm.cc svd.cc syl.cc time.cc gplot.l DLD_SRC := $(addprefix DLD-FUNCTIONS/, $(DLD_XSRC)) @@ -79,6 +80,9 @@ ov-typeinfo.h ov-type-conv.h \ $(OV_INTTYPE_INC) +OV_SPARSE_INCLUDES := \ + ov-base-sparse.h ov-bool-sparse.h ov-cx-sparse.h ov-re-sparse.h + PT_INCLUDES := pt.h pt-all.h pt-arg-list.h pt-assign.h pt-binop.h \ pt-bp.h pt-cell.h pt-check.h pt-cmd.h pt-colon.h pt-const.h \ pt-decl.h pt-except.h pt-exp.h pt-fcn-handle.h pt-id.h pt-idx.h \ @@ -94,8 +98,12 @@ oct-prcstrm.h oct-procbuf.h oct-stdstrm.h oct-stream.h \ oct-strstrm.h oct-lvalue.h oct.h octave.h ops.h pager.h \ parse.h pr-output.h procstream.h sighandlers.h siglist.h \ - symtab.h sysdep.h token.h toplev.h unwind-prot.h utils.h \ - variables.h version.h xdiv.h xpow.h $(OV_INCLUDES) $(PT_INCLUDES) + sparse-ops.h sparse-xdiv.h sparse-xpow.h symtab.h sysdep.h \ + token.h toplev.h unwind-prot.h utils.h variables.h version.h \ + xdiv.h xpow.h \ + $(OV_INCLUDES) \ + $(PT_INCLUDES) \ + $(OV_SPARSE_INCLUDES) TI_XSRC := Array-os.cc Array-sym.cc Array-tc.cc @@ -105,6 +113,14 @@ op-i8-i8.cc op-i16-i16.cc op-i32-i32.cc op-i64-i64.cc \ op-ui8-ui8.cc op-ui16-ui16.cc op-ui32-ui32.cc op-ui64-ui64.cc +SPARSE_OP_XSRC := op-bm-sbm.cc op-b-sbm.cc op-cm-scm.cc op-cm-sm.cc \ + op-cs-scm.cc op-cs-sm.cc op-fil-sbm.cc op-fil-scm.cc \ + op-fil-sm.cc op-m-scm.cc op-m-sm.cc op-sbm-b.cc op-sbm-bm.cc \ + op-sbm-sbm.cc op-scm-cm.cc op-scm-cs.cc op-scm-m.cc \ + op-scm-s.cc op-scm-scm.cc op-scm-sm.cc op-sm-cm.cc \ + op-sm-cs.cc op-sm-m.cc op-sm-s.cc op-sm-scm.cc op-sm-sm.cc \ + op-s-scm.cc op-s-sm.cc + OP_XSRC := op-b-b.cc op-b-bm.cc op-bm-b.cc op-bm-bm.cc \ op-cell.cc op-chm.cc op-cm-cm.cc op-cm-cs.cc op-cm-m.cc \ op-cm-s.cc op-cs-cm.cc op-cs-cs.cc op-cs-m.cc \ @@ -114,7 +130,8 @@ op-m-cs.cc op-m-m.cc op-m-s.cc op-range.cc op-s-cm.cc \ op-s-cs.cc op-s-m.cc op-s-s.cc op-str-m.cc \ op-str-s.cc op-str-str.cc op-streamoff.cc op-struct.cc \ - $(INTTYPE_OP_XSRC) + $(INTTYPE_OP_XSRC) \ + $(SPARSE_OP_XSRC) OP_SRC := $(addprefix OPERATORS/, $(OP_XSRC)) @@ -124,6 +141,9 @@ ov-int8.cc ov-int16.cc ov-int32.cc ov-int64.cc \ ov-uint8.cc ov-uint16.cc ov-uint32.cc ov-uint64.cc +OV_SPARSE_SRC := \ + ov-base-sparse.cc ov-bool-sparse.cc ov-cx-sparse.cc ov-re-sparse.cc + OV_SRC := ov-base.cc ov-ch-mat.cc \ ov-cs-list.cc ov-list.cc ov-re-mat.cc ov-cx-mat.cc \ ov-range.cc ov-scalar.cc ov-complex.cc ov-str-mat.cc \ @@ -131,7 +151,8 @@ ov-colon.cc ov-bool-mat.cc ov-bool.cc ov-file.cc ov-cell.cc \ ov.cc ov-fcn.cc ov-builtin.cc ov-dld-fcn.cc ov-mapper.cc \ ov-usr-fcn.cc ov-fcn-handle.cc ov-fcn-inline.cc ov-typeinfo.cc \ - $(OV_INTTYPE_SRC) + $(OV_INTTYPE_SRC) \ + $(OV_SPARSE_SRC) PT_SRC := pt.cc pt-arg-list.cc pt-assign.cc pt-bp.cc pt-binop.cc \ pt-cell.cc pt-check.cc pt-cmd.cc pt-colon.cc pt-const.cc \ @@ -149,9 +170,10 @@ oct-obj.cc oct-prcstrm.cc oct-procbuf.cc oct-stdstrm.cc \ oct-stream.cc oct-strstrm.cc oct-lvalue.cc pager.cc \ parse.y pr-output.cc procstream.cc sighandlers.cc \ - siglist.c strcasecmp.c strncase.c strfns.cc symtab.cc \ - syscalls.cc sysdep.cc token.cc toplev.cc \ - unwind-prot.cc utils.cc variables.cc xdiv.cc xpow.cc \ + siglist.c sparse-xdiv.cc sparse-xpow.cc strcasecmp.c \ + strncase.c strfns.cc symtab.cc syscalls.cc sysdep.cc \ + token.cc toplev.cc unwind-prot.cc utils.cc variables.cc \ + xdiv.cc xpow.cc \ $(OV_SRC) \ $(PT_SRC) diff --git a/src/OPERATORS/op-b-b.cc b/src/OPERATORS/op-b-b.cc --- a/src/OPERATORS/op-b-b.cc +++ b/src/OPERATORS/op-b-b.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-b-bm.cc b/src/OPERATORS/op-b-bm.cc --- a/src/OPERATORS/op-b-bm.cc +++ b/src/OPERATORS/op-b-bm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-b-sbm.cc b/src/OPERATORS/op-b-sbm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-b-sbm.cc @@ -0,0 +1,96 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-bool.h" +#include "ov-scalar.h" +#include "ops.h" + +#include "ov-re-sparse.h" + +// bool by sparse bool matrix ops. + +DEFBINOP_FN (ne, bool, sparse_bool_matrix, mx_el_ne) +DEFBINOP_FN (eq, bool, sparse_bool_matrix, mx_el_eq) + +DEFBINOP_FN (el_and, bool, sparse_bool_matrix, mx_el_and) +DEFBINOP_FN (el_or, bool, sparse_bool_matrix, mx_el_or) + +DEFCATOP (b_sbm, bool, sparse_bool_matrix) +{ + CAST_BINOP_ARGS (octave_bool&, const octave_sparse_bool_matrix&); + SparseBoolMatrix tmp (1, 1, v1.bool_value ()); + return octave_value (tmp. concat (v2.sparse_bool_matrix_value (), + ra_idx)); +} + +DEFCATOP (b_sm, bool, sparse_matrix) +{ + CAST_BINOP_ARGS (octave_bool&, const octave_sparse_matrix&); + SparseMatrix tmp (1, 1, v1.scalar_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCATOP (s_sbm, scalar, sparse_bool_matrix) +{ + CAST_BINOP_ARGS (octave_scalar&, const octave_sparse_bool_matrix&); + SparseMatrix tmp (1, 1, v1.scalar_value ()); + return octave_value(tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_bool_matrix_conv, bool, sparse_bool_matrix) +{ + CAST_CONV_ARG (const octave_bool&); + + return new octave_sparse_bool_matrix + (SparseBoolMatrix (1, 1, v.bool_value ())); +} + +void +install_b_sbm_ops (void) +{ + INSTALL_BINOP (op_eq, octave_bool, octave_sparse_bool_matrix, eq); + INSTALL_BINOP (op_ne, octave_bool, octave_sparse_bool_matrix, ne); + + INSTALL_BINOP (op_el_and, octave_bool, octave_sparse_bool_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_bool, octave_sparse_bool_matrix, el_or); + + INSTALL_CATOP (octave_bool, octave_sparse_bool_matrix, b_sbm); + INSTALL_CATOP (octave_bool, octave_sparse_matrix, b_sm); + INSTALL_CATOP (octave_scalar, octave_sparse_bool_matrix, s_sbm); + + INSTALL_ASSIGNCONV (octave_bool, octave_sparse_bool_matrix, octave_sparse_bool_matrix); + + INSTALL_WIDENOP (octave_bool, octave_sparse_bool_matrix, sparse_bool_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-bm-b.cc b/src/OPERATORS/op-bm-b.cc --- a/src/OPERATORS/op-bm-b.cc +++ b/src/OPERATORS/op-bm-b.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-bm-bm.cc b/src/OPERATORS/op-bm-bm.cc --- a/src/OPERATORS/op-bm-bm.cc +++ b/src/OPERATORS/op-bm-bm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-bm-sbm.cc b/src/OPERATORS/op-bm-sbm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-bm-sbm.cc @@ -0,0 +1,102 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-bool-mat.h" +#include "boolMatrix.h" +#include "ov-scalar.h" +#include "ops.h" + +#include "ov-re-sparse.h" +#include "smx-bm-sbm.h" +#include "smx-sbm-bm.h" + +// bool matrix by sparse bool matrix ops. + +DEFBINOP_FN (eq, bool_matrix, sparse_bool_matrix, mx_el_eq) +DEFBINOP_FN (ne, bool_matrix, sparse_bool_matrix, mx_el_ne) + +DEFBINOP_FN (el_and, bool_matrix, sparse_bool_matrix, mx_el_and) +DEFBINOP_FN (el_or, bool_matrix, sparse_bool_matrix, mx_el_or) + +DEFCATOP (bm_sbm, bool_matrix, sparse_bool_matrix) +{ + CAST_BINOP_ARGS (octave_bool_matrix&, const octave_sparse_bool_matrix&); + SparseBoolMatrix tmp (v1.bool_matrix_value ()); + return octave_value (tmp. concat (v2.sparse_bool_matrix_value (), + ra_idx)); +} + +DEFCATOP (m_sbm, matrix, sparse_bool_matrix) +{ + CAST_BINOP_ARGS (octave_matrix&, const octave_sparse_bool_matrix&); + SparseMatrix tmp (v1.matrix_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCATOP (bm_sm, bool_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (octave_bool_matrix&, const octave_sparse_matrix&); + SparseMatrix tmp (v1.matrix_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_bool_matrix_conv, bool_matrix, sparse_bool_matrix) +{ + CAST_CONV_ARG (const octave_bool_matrix&); + return new octave_sparse_bool_matrix + (SparseBoolMatrix (v.bool_matrix_value ())); +} + +void +install_bm_sbm_ops (void) +{ + INSTALL_BINOP (op_eq, octave_bool_matrix, octave_sparse_bool_matrix, eq); + INSTALL_BINOP (op_ne, octave_bool_matrix, octave_sparse_bool_matrix, ne); + + INSTALL_BINOP (op_el_and, octave_bool_matrix, octave_sparse_bool_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_bool_matrix, octave_sparse_bool_matrix, + el_or); + + INSTALL_CATOP (octave_bool_matrix, octave_sparse_bool_matrix, bm_sbm); + INSTALL_CATOP (octave_bool_matrix, octave_sparse_matrix, bm_sm); + INSTALL_CATOP (octave_matrix, octave_sparse_bool_matrix, m_sbm); + + INSTALL_ASSIGNCONV (octave_bool_matrix, octave_sparse_bool_matrix, + octave_sparse_bool_matrix); + + INSTALL_WIDENOP (octave_bool_matrix, octave_sparse_bool_matrix, + sparse_bool_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-cell.cc b/src/OPERATORS/op-cell.cc --- a/src/OPERATORS/op-cell.cc +++ b/src/OPERATORS/op-cell.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-chm.cc b/src/OPERATORS/op-chm.cc --- a/src/OPERATORS/op-chm.cc +++ b/src/OPERATORS/op-chm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cm-cm.cc b/src/OPERATORS/op-cm-cm.cc --- a/src/OPERATORS/op-cm-cm.cc +++ b/src/OPERATORS/op-cm-cm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cm-cs.cc b/src/OPERATORS/op-cm-cs.cc --- a/src/OPERATORS/op-cm-cs.cc +++ b/src/OPERATORS/op-cm-cs.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cm-m.cc b/src/OPERATORS/op-cm-m.cc --- a/src/OPERATORS/op-cm-m.cc +++ b/src/OPERATORS/op-cm-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cm-s.cc b/src/OPERATORS/op-cm-s.cc --- a/src/OPERATORS/op-cm-s.cc +++ b/src/OPERATORS/op-cm-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cm-scm.cc b/src/OPERATORS/op-cm-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-cm-scm.cc @@ -0,0 +1,182 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-scm-cm.h" +#include "smx-cm-scm.h" +#include "ov-cx-sparse.h" + +// complex matrix by sparse complex matrix ops. + +DEFBINOP_OP (add, complex_matrix, sparse_complex_matrix,+) +DEFBINOP_OP (sub, complex_matrix, sparse_complex_matrix,-) + +DEFBINOP (mul, complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_complex_matrix&); + + ComplexMatrix tmp (v2.complex_matrix_value ()); + + return octave_value ( v1.complex_matrix_value() * tmp); +} + +DEFBINOP (div, complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_complex_matrix&); + + return xdiv (v1.complex_matrix_value (), + v2.sparse_complex_matrix_value ()); +} + +DEFBINOPX (pow, complex_matrix, sparse_complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_complex_matrix&); + + return xleftdiv (v1.complex_matrix_value (), + v2.complex_matrix_value ()); +} + +DEFBINOP_FN (lt, complex_matrix, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, complex_matrix, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, complex_matrix, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, complex_matrix, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, complex_matrix, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, complex_matrix, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, complex_matrix, sparse_complex_matrix, product) +DEFBINOP_FN (el_div, complex_matrix, sparse_complex_matrix, quotient) + +DEFBINOP (el_pow, complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_complex_matrix&); + + return octave_value + (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()), + v2.sparse_complex_matrix_value ())); +} + +DEFBINOP (el_ldiv, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_complex_matrix&); + + return octave_value (quotient (v2.sparse_complex_matrix_value (), + v1.complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, complex_matrix, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, complex_matrix, sparse_complex_matrix, mx_el_or) + +DEFCATOP (cm_scm, complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (octave_complex_matrix&, + const octave_sparse_complex_matrix&); + SparseComplexMatrix tmp (v1.complex_matrix_value ()); + return octave_value (tmp. concat (v2.sparse_complex_matrix_value (), + ra_idx)); +} + +DEFCONV (sparse_complex_matrix_conv, complex_matrix, + sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_complex_matrix&); + return new octave_sparse_complex_matrix + (SparseComplexMatrix (v.complex_matrix_value ())); +} + +void +install_cm_scm_ops (void) +{ + INSTALL_BINOP (op_add, octave_complex_matrix, + octave_sparse_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_complex_matrix, + octave_sparse_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_complex_matrix, + octave_sparse_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_complex_matrix, + octave_sparse_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_complex_matrix, + octave_sparse_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_complex_matrix, + octave_sparse_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_complex_matrix, + octave_sparse_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_complex_matrix, + octave_sparse_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_complex_matrix, + octave_sparse_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_complex_matrix, + octave_sparse_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_complex_matrix, + octave_sparse_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_complex_matrix, + octave_sparse_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_complex_matrix, + octave_sparse_complex_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_complex_matrix, + octave_sparse_complex_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_complex_matrix, + octave_sparse_complex_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_complex_matrix, + octave_sparse_complex_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_complex_matrix, + octave_sparse_complex_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_complex_matrix, + octave_sparse_complex_matrix, el_or); + + INSTALL_CATOP (octave_complex_matrix, + octave_sparse_complex_matrix, cm_scm); + + INSTALL_ASSIGNCONV (octave_complex_matrix, octave_sparse_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_complex_matrix, octave_sparse_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-cm-sm.cc b/src/OPERATORS/op-cm-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-cm-sm.cc @@ -0,0 +1,151 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-sm-cm.h" +#include "smx-cm-sm.h" +#include "ov-re-sparse.h" + +// complex matrix by sparse matrix ops. + +DEFBINOP_OP (add, complex_matrix, sparse_matrix, +) +DEFBINOP_OP (sub, complex_matrix, sparse_matrix, -) + +DEFBINOP (mul, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_matrix&); + + Matrix tmp (v2.matrix_value ()); + + return octave_value (v1.complex_matrix_value() * tmp); +} + +DEFBINOP (div, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_matrix&); + + return xdiv (v1.complex_matrix_value (), v2.sparse_matrix_value ()); +} + +DEFBINOPX (pow, complex_matrix, sparse_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_matrix&); + + return xleftdiv (v1.complex_matrix_value (), v2.matrix_value ()); +} + +DEFBINOP_FN (lt, complex_matrix, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, complex_matrix, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, complex_matrix, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, complex_matrix, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, complex_matrix, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, complex_matrix, sparse_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, complex_matrix, sparse_matrix, product) +DEFBINOP_FN (el_div, complex_matrix, sparse_matrix, quotient) + +DEFBINOP (el_pow, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_matrix&); + + return octave_value + (elem_xpow ( SparseComplexMatrix (v1.complex_matrix_value ()), + v2.sparse_matrix_value ())); +} + +DEFBINOP (el_ldiv, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex_matrix&, + const octave_sparse_matrix&); + return octave_value + (quotient (v2.sparse_matrix_value (), v1.complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, complex_matrix, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, complex_matrix, sparse_matrix, mx_el_or) + +DEFCATOP (cm_sm, complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (octave_complex_matrix&, const octave_sparse_matrix&); + SparseComplexMatrix tmp (v1.complex_matrix_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +void +install_cm_sm_ops (void) +{ + INSTALL_BINOP (op_add, octave_complex_matrix, octave_sparse_matrix, add); + INSTALL_BINOP (op_sub, octave_complex_matrix, octave_sparse_matrix, sub); + INSTALL_BINOP (op_mul, octave_complex_matrix, octave_sparse_matrix, mul); + INSTALL_BINOP (op_div, octave_complex_matrix, octave_sparse_matrix, div); + INSTALL_BINOP (op_pow, octave_complex_matrix, octave_sparse_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_complex_matrix, octave_sparse_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_complex_matrix, octave_sparse_matrix, lt); + INSTALL_BINOP (op_le, octave_complex_matrix, octave_sparse_matrix, le); + INSTALL_BINOP (op_eq, octave_complex_matrix, octave_sparse_matrix, eq); + INSTALL_BINOP (op_ge, octave_complex_matrix, octave_sparse_matrix, ge); + INSTALL_BINOP (op_gt, octave_complex_matrix, octave_sparse_matrix, gt); + INSTALL_BINOP (op_ne, octave_complex_matrix, octave_sparse_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_complex_matrix, octave_sparse_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_complex_matrix, octave_sparse_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_complex_matrix, octave_sparse_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_complex_matrix, octave_sparse_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_complex_matrix, octave_sparse_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_complex_matrix, octave_sparse_matrix, + el_or); + + INSTALL_CATOP (octave_complex_matrix, octave_sparse_matrix, cm_sm); + +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-cs-cm.cc b/src/OPERATORS/op-cs-cm.cc --- a/src/OPERATORS/op-cs-cm.cc +++ b/src/OPERATORS/op-cs-cm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cs-cs.cc b/src/OPERATORS/op-cs-cs.cc --- a/src/OPERATORS/op-cs-cs.cc +++ b/src/OPERATORS/op-cs-cs.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cs-m.cc b/src/OPERATORS/op-cs-m.cc --- a/src/OPERATORS/op-cs-m.cc +++ b/src/OPERATORS/op-cs-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cs-s.cc b/src/OPERATORS/op-cs-s.cc --- a/src/OPERATORS/op-cs-s.cc +++ b/src/OPERATORS/op-cs-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-cs-scm.cc b/src/OPERATORS/op-cs-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-cs-scm.cc @@ -0,0 +1,167 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ov-complex.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-cx-sparse.h" + +// complex scalar by sparse complex matrix ops. + +DEFBINOP_OP (add, complex, sparse_complex_matrix, +) +DEFBINOP_OP (sub, complex, sparse_complex_matrix, -) +DEFBINOP_OP (mul, complex, sparse_complex_matrix, *) + +DEFBINOP (div, complex, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, + const octave_sparse_complex_matrix&); + + ComplexMatrix m1 = ComplexMatrix (1, 1, v1.complex_value ()); + SparseComplexMatrix m2 = v2.sparse_complex_matrix_value (); + + return xdiv (m1, m2); +} + +DEFBINOP (pow, complex, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, + const octave_sparse_complex_matrix&); + return xpow (v1.complex_value (), v2.complex_matrix_value ()); +} + +DEFBINOP (ldiv, complex, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_complex_matrix&); + + Complex d = v1.complex_value (); + + if (d == 0.0) + gripe_divide_by_zero (); + + return octave_value (v2.sparse_complex_matrix_value () / d); +} + +DEFBINOP_FN (lt, complex, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, complex, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, complex, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, complex, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, complex, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, complex, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_OP (el_mul, complex, sparse_complex_matrix, *) +DEFBINOP_FN (el_div, complex, sparse_complex_matrix, x_el_div) + +DEFBINOP_FN (el_pow, complex, sparse_complex_matrix, elem_xpow) + +DEFBINOP (el_ldiv, complex, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_complex_matrix&); + + Complex d = v1.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.complex_matrix_value () / d); + } + else + retval = octave_value (v2.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_and, complex, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, complex, sparse_complex_matrix, mx_el_or) + +DEFCATOP (cs_scm, complex, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (octave_complex&, const octave_sparse_complex_matrix&); + SparseComplexMatrix tmp (1, 1, v1.complex_value ()); + return octave_value (tmp. concat (v2.sparse_complex_matrix_value (), + ra_idx)); +} + +DEFCONV (sparse_complex_matrix_conv, complex, sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_complex&); + + return new octave_sparse_complex_matrix + (SparseComplexMatrix (v.complex_matrix_value ())); +} + +void +install_cs_scm_ops (void) +{ + INSTALL_BINOP (op_add, octave_complex, octave_sparse_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_complex, octave_sparse_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_complex, octave_sparse_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_complex, octave_sparse_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_complex, octave_sparse_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_complex, octave_sparse_complex_matrix, + ldiv); + INSTALL_BINOP (op_lt, octave_complex, octave_sparse_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_complex, octave_sparse_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_complex, octave_sparse_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_complex, octave_sparse_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_complex, octave_sparse_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_complex, octave_sparse_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_complex, octave_sparse_complex_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_complex, octave_sparse_complex_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_complex, octave_sparse_complex_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_complex, octave_sparse_complex_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_complex, octave_sparse_complex_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_complex, octave_sparse_complex_matrix, + el_or); + + INSTALL_CATOP (octave_complex, octave_sparse_complex_matrix, cs_scm); + + INSTALL_ASSIGNCONV (octave_complex, octave_sparse_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_complex, octave_sparse_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-cs-sm.cc b/src/OPERATORS/op-cs-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-cs-sm.cc @@ -0,0 +1,163 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-complex.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" +#include "smx-cs-sm.h" +#include "smx-sm-cs.h" + +// complex by sparse matrix ops. + +DEFBINOP_OP (add, complex, sparse_matrix, +) +DEFBINOP_OP (sub, complex, sparse_matrix, -) +DEFBINOP_OP (mul, complex, sparse_matrix, *) + +DEFBINOP (div, complex, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_matrix&); + + ComplexMatrix m1 = ComplexMatrix (1, 1, v1.complex_value ()); + SparseMatrix m2 = v2.sparse_matrix_value (); + + return xdiv (m1, m2); +} + +DEFBINOP (pow, complex, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_matrix&); + return xpow (v1.complex_value (), v2.matrix_value ()); +} + +DEFBINOP (ldiv, complex, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_matrix&); + + Complex d = v1.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.matrix_value () / d); + } + else + retval = octave_value (v2.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (lt, complex, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, complex, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, complex, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, complex, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, complex, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, complex, sparse_matrix, mx_el_ne) + +DEFBINOP_OP (el_mul, complex, sparse_matrix, *) +DEFBINOP_FN (el_div, complex, sparse_matrix, x_el_div) +DEFBINOP_FN (el_pow, complex, sparse_matrix, elem_xpow) + +DEFBINOP (el_ldiv, complex, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_complex&, const octave_sparse_matrix&); + + Complex d = v1.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.matrix_value () / d); + } + else + retval = octave_value (v2.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_and, complex, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, complex, sparse_matrix, mx_el_or) + +DEFCATOP (cs_sm, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (octave_complex&, const octave_sparse_matrix&); + SparseComplexMatrix tmp (1, 1, v1.complex_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_matrix_conv, complex, sparse_matrix) +{ + CAST_CONV_ARG (const octave_complex&); + + return new octave_sparse_matrix + (SparseMatrix (v.matrix_value ())); +} + +void +install_cs_sm_ops (void) +{ + INSTALL_BINOP (op_add, octave_complex, octave_sparse_matrix, add); + INSTALL_BINOP (op_sub, octave_complex, octave_sparse_matrix, sub); + INSTALL_BINOP (op_mul, octave_complex, octave_sparse_matrix, mul); + INSTALL_BINOP (op_div, octave_complex, octave_sparse_matrix, div); + INSTALL_BINOP (op_pow, octave_complex, octave_sparse_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_complex, octave_sparse_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_complex, octave_sparse_matrix, lt); + INSTALL_BINOP (op_le, octave_complex, octave_sparse_matrix, le); + INSTALL_BINOP (op_eq, octave_complex, octave_sparse_matrix, eq); + INSTALL_BINOP (op_ge, octave_complex, octave_sparse_matrix, ge); + INSTALL_BINOP (op_gt, octave_complex, octave_sparse_matrix, gt); + INSTALL_BINOP (op_ne, octave_complex, octave_sparse_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_complex, octave_sparse_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_complex, octave_sparse_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_complex, octave_sparse_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_complex, octave_sparse_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_complex, octave_sparse_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_complex, octave_sparse_matrix, el_or); + + INSTALL_CATOP (octave_complex, octave_sparse_matrix, cs_sm); + + INSTALL_ASSIGNCONV (octave_complex, octave_sparse_matrix, octave_sparse_matrix); + + INSTALL_WIDENOP (octave_complex, octave_sparse_matrix, sparse_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-double-conv.cc b/src/OPERATORS/op-double-conv.cc --- a/src/OPERATORS/op-double-conv.cc +++ b/src/OPERATORS/op-double-conv.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif @@ -41,6 +37,8 @@ #include "ov-uint64.h" #include "ov-bool.h" #include "ov-bool-mat.h" +#include "ov-re-sparse.h" +#include "ov-bool-sparse.h" #include "ov-range.h" #include "ov-scalar.h" #include "ov-re-mat.h" @@ -73,6 +71,9 @@ DEFDBLCONVFN (bool_matrix_to_double_matrix, bool_matrix, bool_array) DEFDBLCONVFN (bool_scalar_to_double_matrix, bool, bool_array) +DEFDBLCONVFN (sparse_matrix_to_double_matrix, sparse_matrix, array) +DEFDBLCONVFN (sparse_bool_matrix_to_double_matrix, sparse_bool_matrix, array) + DEFDBLCONVFN (range_to_double_matrix, range, array) DEFSTRDBLCONVFN(char_matrix_str_to_double_matrix) @@ -105,6 +106,9 @@ INSTALL_CONVOP (octave_bool_matrix, octave_matrix, bool_matrix_to_double_matrix); INSTALL_CONVOP (octave_bool, octave_matrix, bool_scalar_to_double_matrix); + INSTALL_CONVOP (octave_sparse_matrix, octave_matrix, sparse_matrix_to_double_matrix); + INSTALL_CONVOP (octave_sparse_bool_matrix, octave_matrix, sparse_bool_matrix_to_double_matrix); + INSTALL_CONVOP (octave_range, octave_matrix, range_to_double_matrix); INSTALL_CONVOP (octave_char_matrix_str, octave_matrix, char_matrix_str_to_double_matrix); diff --git a/src/OPERATORS/op-fil-b.cc b/src/OPERATORS/op-fil-b.cc --- a/src/OPERATORS/op-fil-b.cc +++ b/src/OPERATORS/op-fil-b.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-bm.cc b/src/OPERATORS/op-fil-bm.cc --- a/src/OPERATORS/op-fil-bm.cc +++ b/src/OPERATORS/op-fil-bm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-cm.cc b/src/OPERATORS/op-fil-cm.cc --- a/src/OPERATORS/op-fil-cm.cc +++ b/src/OPERATORS/op-fil-cm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-cs.cc b/src/OPERATORS/op-fil-cs.cc --- a/src/OPERATORS/op-fil-cs.cc +++ b/src/OPERATORS/op-fil-cs.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-lis.cc b/src/OPERATORS/op-fil-lis.cc --- a/src/OPERATORS/op-fil-lis.cc +++ b/src/OPERATORS/op-fil-lis.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-m.cc b/src/OPERATORS/op-fil-m.cc --- a/src/OPERATORS/op-fil-m.cc +++ b/src/OPERATORS/op-fil-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-rec.cc b/src/OPERATORS/op-fil-rec.cc --- a/src/OPERATORS/op-fil-rec.cc +++ b/src/OPERATORS/op-fil-rec.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-s.cc b/src/OPERATORS/op-fil-s.cc --- a/src/OPERATORS/op-fil-s.cc +++ b/src/OPERATORS/op-fil-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-fil-sbm.cc b/src/OPERATORS/op-fil-sbm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-fil-sbm.cc @@ -0,0 +1,74 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "mach-info.h" +#include "error.h" +#include "oct-obj.h" +#include "oct-stream.h" +#include "ops.h" +#include "ov.h" +#include "ov-file.h" +#include "ov-typeinfo.h" + +#include "ov-bool-sparse.h" + +// file by sparse bool matrix ops. + +DEFBINOP (lshift, file, sparse_bool_matrix) +{ + CAST_BINOP_ARGS (const octave_file&, const octave_sparse_bool_matrix&); + + octave_stream oct_stream = v1.stream_value (); + + if (oct_stream) + { + std::ostream *osp = oct_stream.output_stream (); + + if (osp) + { + std::ostream& os = *osp; + + v2.print_raw (os); + } + else + error ("invalid file specified for binary operator `<<'"); + } + + return octave_value (oct_stream, v1.stream_number ()); +} + +void +install_fil_sbm_ops (void) +{ + INSTALL_BINOP (op_lshift, octave_file, octave_sparse_bool_matrix, lshift); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-fil-scm.cc b/src/OPERATORS/op-fil-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-fil-scm.cc @@ -0,0 +1,75 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "mach-info.h" +#include "error.h" +#include "oct-obj.h" +#include "oct-stream.h" +#include "ops.h" +#include "ov.h" +#include "ov-file.h" +#include "ov-typeinfo.h" + +#include "ov-cx-sparse.h" + +// file by sparse complex matrix ops. + +DEFBINOP (lshift, file, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_file&, const octave_sparse_complex_matrix&); + + octave_stream oct_stream = v1.stream_value (); + + if (oct_stream) + { + std::ostream *osp = oct_stream.output_stream (); + + if (osp) + { + std::ostream& os = *osp; + + v2.print_raw (os); + } + else + error ("invalid file specified for binary operator `<<'"); + } + + return octave_value (oct_stream, v1.stream_number ()); +} + +void +install_fil_scm_ops (void) +{ + INSTALL_BINOP (op_lshift, octave_file, octave_sparse_complex_matrix, + lshift); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-fil-sm.cc b/src/OPERATORS/op-fil-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-fil-sm.cc @@ -0,0 +1,74 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "mach-info.h" +#include "error.h" +#include "oct-obj.h" +#include "oct-stream.h" +#include "ops.h" +#include "ov.h" +#include "ov-file.h" +#include "ov-typeinfo.h" + +#include "ov-re-sparse.h" + +// file by sparse matrix ops. + +DEFBINOP (lshift, file, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_file&, const octave_sparse_matrix&); + + octave_stream oct_stream = v1.stream_value (); + + if (oct_stream) + { + std::ostream *osp = oct_stream.output_stream (); + + if (osp) + { + std::ostream& os = *osp; + + v2.print_raw (os); + } + else + error ("invalid file specified for binary operator `<<'"); + } + + return octave_value (oct_stream, v1.stream_number ()); +} + +void +install_fil_sm_ops (void) +{ + INSTALL_BINOP (op_lshift, octave_file, octave_sparse_matrix, lshift); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-fil-str.cc b/src/OPERATORS/op-fil-str.cc --- a/src/OPERATORS/op-fil-str.cc +++ b/src/OPERATORS/op-fil-str.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-i16-i16.cc b/src/OPERATORS/op-i16-i16.cc --- a/src/OPERATORS/op-i16-i16.cc +++ b/src/OPERATORS/op-i16-i16.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-i32-i32.cc b/src/OPERATORS/op-i32-i32.cc --- a/src/OPERATORS/op-i32-i32.cc +++ b/src/OPERATORS/op-i32-i32.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-i64-i64.cc b/src/OPERATORS/op-i64-i64.cc --- a/src/OPERATORS/op-i64-i64.cc +++ b/src/OPERATORS/op-i64-i64.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-i8-i8.cc b/src/OPERATORS/op-i8-i8.cc --- a/src/OPERATORS/op-i8-i8.cc +++ b/src/OPERATORS/op-i8-i8.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-int-conv.cc b/src/OPERATORS/op-int-conv.cc --- a/src/OPERATORS/op-int-conv.cc +++ b/src/OPERATORS/op-int-conv.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-list.cc b/src/OPERATORS/op-list.cc --- a/src/OPERATORS/op-list.cc +++ b/src/OPERATORS/op-list.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-m-cm.cc b/src/OPERATORS/op-m-cm.cc --- a/src/OPERATORS/op-m-cm.cc +++ b/src/OPERATORS/op-m-cm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-m-cs.cc b/src/OPERATORS/op-m-cs.cc --- a/src/OPERATORS/op-m-cs.cc +++ b/src/OPERATORS/op-m-cs.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-m-m.cc b/src/OPERATORS/op-m-m.cc --- a/src/OPERATORS/op-m-m.cc +++ b/src/OPERATORS/op-m-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-m-s.cc b/src/OPERATORS/op-m-s.cc --- a/src/OPERATORS/op-m-s.cc +++ b/src/OPERATORS/op-m-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-m-scm.cc b/src/OPERATORS/op-m-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-m-scm.cc @@ -0,0 +1,165 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-re-mat.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-scm-m.h" +#include "smx-m-scm.h" +#include "ov-cx-sparse.h" + +// matrix by sparse complex matrix ops. + +DEFBINOP_OP (add, matrix, sparse_complex_matrix, +) +DEFBINOP_OP (sub, matrix, sparse_complex_matrix, -) + +DEFBINOP (mul, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, + const octave_sparse_complex_matrix&); + + ComplexMatrix tmp (v2.complex_matrix_value ()); + + return octave_value ( v1.matrix_value() * tmp); +} + +DEFBINOP (div, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, + const octave_sparse_complex_matrix&); + + return xdiv (v1.matrix_value (), v2.sparse_complex_matrix_value ()); +} + +DEFBINOPX (pow, matrix, sparse_complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, + const octave_sparse_complex_matrix&); + + return xleftdiv (v1.matrix_value (), v2.complex_matrix_value ()); +} + +DEFBINOP_FN (lt, matrix, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, matrix, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, matrix, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, matrix, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, matrix, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, matrix, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, matrix, sparse_complex_matrix, product) +DEFBINOP_FN (el_div, matrix, sparse_complex_matrix, quotient) + +DEFBINOP (el_pow, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, + const octave_sparse_complex_matrix&); + + return octave_value + (elem_xpow (SparseMatrix (v1.matrix_value ()), + v2.sparse_complex_matrix_value ())); +} + +DEFBINOP (el_ldiv, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, + const octave_sparse_complex_matrix&); + return octave_value + (quotient (v2.sparse_complex_matrix_value (), v1.matrix_value ())); +} + +DEFBINOP_FN (el_and, matrix, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, matrix, sparse_complex_matrix, mx_el_or) + +DEFCATOP (m_scm, matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (octave_matrix&, const octave_sparse_complex_matrix&); + SparseMatrix tmp (v1.matrix_value ()); + return octave_value (tmp. concat (v2.sparse_complex_matrix_value (), + ra_idx)); +} + +DEFCONV (sparse_complex_matrix_conv, matrix, sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_matrix&); + return new octave_sparse_complex_matrix + (SparseComplexMatrix (v.complex_matrix_value ())); +} + +void +install_m_scm_ops (void) +{ + INSTALL_BINOP (op_add, octave_matrix, octave_sparse_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_matrix, octave_sparse_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_matrix, octave_sparse_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_matrix, octave_sparse_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_matrix, octave_sparse_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_matrix, octave_sparse_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_matrix, octave_sparse_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_matrix, octave_sparse_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_matrix, octave_sparse_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_matrix, octave_sparse_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_matrix, octave_sparse_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_matrix, octave_sparse_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_matrix, octave_sparse_complex_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_matrix, octave_sparse_complex_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_matrix, octave_sparse_complex_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_matrix, octave_sparse_complex_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_matrix, octave_sparse_complex_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_matrix, octave_sparse_complex_matrix, + el_or); + + INSTALL_CATOP (octave_matrix, octave_sparse_complex_matrix, m_scm); + + INSTALL_ASSIGNCONV (octave_matrix, octave_sparse_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_matrix, octave_sparse_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-m-sm.cc b/src/OPERATORS/op-m-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-m-sm.cc @@ -0,0 +1,151 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-re-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-sm-m.h" +#include "smx-m-sm.h" +#include "ov-re-sparse.h" + +// matrix by sparse matrix ops. + +DEFBINOP_OP (add, matrix, sparse_matrix, +) +DEFBINOP_OP (sub, matrix, sparse_matrix, -) + +DEFBINOP (mul, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_sparse_matrix&); + + Matrix tmp (v2.matrix_value ()); + + return octave_value ( v1.matrix_value() * tmp); +} + +DEFBINOP (div, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_sparse_matrix&); + + return xdiv (v1.matrix_value (), v2.sparse_matrix_value ()); +} + +DEFBINOPX (pow, matrix, sparse_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_sparse_matrix&); + + return xleftdiv (v1.matrix_value (), v2.matrix_value ()); +} + +DEFBINOP_FN (lt, matrix, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, matrix, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, matrix, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, matrix, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, matrix, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, matrix, sparse_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, matrix, sparse_matrix, product) +DEFBINOP_FN (el_div, matrix, sparse_matrix, quotient) + +DEFBINOP (el_pow, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_sparse_matrix&); + + return octave_value (elem_xpow (SparseMatrix (v1.matrix_value ()), + v2.sparse_matrix_value ())); +} + +DEFBINOP (el_ldiv, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_sparse_matrix&); + + return octave_value + (quotient (v2.sparse_matrix_value (), v1.matrix_value ())); +} + +DEFBINOP_FN (el_and, matrix, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, matrix, sparse_matrix, mx_el_or) + +DEFCATOP (m_sm, matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (octave_matrix&, const octave_sparse_matrix&); + SparseMatrix tmp (v1.matrix_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_matrix_conv, matrix, sparse_matrix) +{ + CAST_CONV_ARG (const octave_matrix&); + return new octave_sparse_matrix (SparseMatrix (v.matrix_value ())); +} + +void +install_m_sm_ops (void) +{ + INSTALL_BINOP (op_add, octave_matrix, octave_sparse_matrix, add); + INSTALL_BINOP (op_sub, octave_matrix, octave_sparse_matrix, sub); + INSTALL_BINOP (op_mul, octave_matrix, octave_sparse_matrix, mul); + INSTALL_BINOP (op_div, octave_matrix, octave_sparse_matrix, div); + INSTALL_BINOP (op_pow, octave_matrix, octave_sparse_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_matrix, octave_sparse_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_matrix, octave_sparse_matrix, lt); + INSTALL_BINOP (op_le, octave_matrix, octave_sparse_matrix, le); + INSTALL_BINOP (op_eq, octave_matrix, octave_sparse_matrix, eq); + INSTALL_BINOP (op_ge, octave_matrix, octave_sparse_matrix, ge); + INSTALL_BINOP (op_gt, octave_matrix, octave_sparse_matrix, gt); + INSTALL_BINOP (op_ne, octave_matrix, octave_sparse_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_matrix, octave_sparse_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_matrix, octave_sparse_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_matrix, octave_sparse_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_matrix, octave_sparse_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_matrix, octave_sparse_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_matrix, octave_sparse_matrix, el_or); + + INSTALL_CATOP (octave_matrix, octave_sparse_matrix, m_sm); + + INSTALL_ASSIGNCONV (octave_matrix, octave_sparse_matrix, + octave_sparse_matrix); + + INSTALL_WIDENOP (octave_matrix, octave_sparse_matrix, + sparse_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-range.cc b/src/OPERATORS/op-range.cc --- a/src/OPERATORS/op-range.cc +++ b/src/OPERATORS/op-range.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-s-cm.cc b/src/OPERATORS/op-s-cm.cc --- a/src/OPERATORS/op-s-cm.cc +++ b/src/OPERATORS/op-s-cm.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-s-cs.cc b/src/OPERATORS/op-s-cs.cc --- a/src/OPERATORS/op-s-cs.cc +++ b/src/OPERATORS/op-s-cs.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-s-m.cc b/src/OPERATORS/op-s-m.cc --- a/src/OPERATORS/op-s-m.cc +++ b/src/OPERATORS/op-s-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-s-s.cc b/src/OPERATORS/op-s-s.cc --- a/src/OPERATORS/op-s-s.cc +++ b/src/OPERATORS/op-s-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-s-scm.cc b/src/OPERATORS/op-s-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-s-scm.cc @@ -0,0 +1,177 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ov-scalar.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-s-scm.h" +#include "smx-scm-s.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// scalar by sparse complex matrix ops. + +DEFBINOP_OP (add, scalar, sparse_complex_matrix, +) +DEFBINOP_OP (sub, scalar, sparse_complex_matrix, -) +DEFBINOP_OP (mul, scalar, sparse_complex_matrix, *) + +DEFBINOP (div, scalar, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, + const octave_sparse_complex_matrix&); + + Matrix m1 = Matrix (1, 1, v1.scalar_value ()); + SparseComplexMatrix m2 = v2.sparse_complex_matrix_value (); + + return xdiv (m1, m2); +} + +DEFBINOP (pow, scalar, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, + const octave_sparse_complex_matrix&); + return xpow (v1.scalar_value (), v2.complex_matrix_value ()); +} + +DEFBINOP (ldiv, scalar, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, + const octave_sparse_complex_matrix&); + + double d = v1.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.complex_matrix_value () / d); + } + else + retval = octave_value (v2.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (lt, scalar, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, scalar, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, scalar, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, scalar, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, scalar, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, scalar, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_OP (el_mul, scalar, sparse_complex_matrix, *) +DEFBINOP_FN (el_div, scalar, sparse_complex_matrix, x_el_div) +DEFBINOP_FN (el_pow, scalar, sparse_complex_matrix, elem_xpow) + +DEFBINOP (el_ldiv, scalar, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, + const octave_sparse_complex_matrix&); + + double d = v1.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.complex_matrix_value () / d); + } + else + retval = octave_value (v2.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_and, scalar, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, scalar, sparse_complex_matrix, mx_el_or) + +DEFCATOP (s_scm, scalar, sparse_compelx_matrix) +{ + CAST_BINOP_ARGS (octave_scalar&, const octave_sparse_complex_matrix&); + SparseMatrix tmp (1, 1, v1.scalar_value ()); + return octave_value + (tmp. concat (v2.sparse_complex_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_complex_matrix_conv, scalar, sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_scalar&); + + return new octave_sparse_complex_matrix + (SparseComplexMatrix (v.complex_matrix_value ())); +} + +void +install_s_scm_ops (void) +{ + INSTALL_BINOP (op_add, octave_scalar, octave_sparse_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_scalar, octave_sparse_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_scalar, octave_sparse_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_scalar, octave_sparse_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_scalar, octave_sparse_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_scalar, octave_sparse_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_scalar, octave_sparse_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_scalar, octave_sparse_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_scalar, octave_sparse_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_scalar, octave_sparse_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_scalar, octave_sparse_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_scalar, octave_sparse_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_scalar, octave_sparse_complex_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_scalar, octave_sparse_complex_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_scalar, octave_sparse_complex_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_scalar, octave_sparse_complex_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_scalar, octave_sparse_complex_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_scalar, octave_sparse_complex_matrix, + el_or); + + INSTALL_CATOP (octave_scalar, octave_sparse_complex_matrix, s_scm); + + INSTALL_ASSIGNCONV (octave_scalar, octave_sparse_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_scalar, octave_sparse_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-s-sm.cc b/src/OPERATORS/op-s-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-s-sm.cc @@ -0,0 +1,159 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-scalar.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-re-sparse.h" + +// scalar by sparse matrix ops. + +DEFBINOP_OP (add, scalar, sparse_matrix, +) +DEFBINOP_OP (sub, scalar, sparse_matrix, -) +DEFBINOP_OP (mul, scalar, sparse_matrix, *) + +DEFBINOP (div, scalar, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_sparse_matrix&); + + Matrix m1 = Matrix (1, 1, v1.double_value ()); + SparseMatrix m2 = v2.sparse_matrix_value (); + + return xdiv (m1, m2); +} + +DEFBINOP (pow, scalar, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_sparse_matrix&); + return xpow (v1.scalar_value (), v2.matrix_value ()); +} + +DEFBINOP (ldiv, scalar, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_sparse_matrix&); + + double d = v1.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.matrix_value () / d); + } + else + retval = octave_value (v2.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (lt, scalar, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, scalar, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, scalar, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, scalar, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, scalar, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, scalar, sparse_matrix, mx_el_ne) + +DEFBINOP_OP (el_mul, scalar, sparse_matrix, *) +DEFBINOP_FN (el_div, scalar, sparse_matrix, x_el_div) +DEFBINOP_FN (el_pow, scalar, sparse_matrix, elem_xpow) + +DEFBINOP (el_ldiv, scalar, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_sparse_matrix&); + + double d = v1.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v2.matrix_value () / d); + } + else + retval = octave_value (v2.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_and, scalar, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, scalar, sparse_matrix, mx_el_or) + +DEFCATOP (s_sm, scalar, sparse_matrix) +{ + CAST_BINOP_ARGS (octave_scalar&, const octave_sparse_matrix&); + SparseMatrix tmp (1, 1, v1.scalar_value ()); + return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx)); +} + +DEFCONV (sparse_matrix_conv, scalar, sparse_matrix) +{ + CAST_CONV_ARG (const octave_scalar&); + + return new octave_sparse_matrix (SparseMatrix (v.matrix_value ())); +} + +void +install_s_sm_ops (void) +{ + INSTALL_BINOP (op_add, octave_scalar, octave_sparse_matrix, add); + INSTALL_BINOP (op_sub, octave_scalar, octave_sparse_matrix, sub); + INSTALL_BINOP (op_mul, octave_scalar, octave_sparse_matrix, mul); + INSTALL_BINOP (op_div, octave_scalar, octave_sparse_matrix, div); + INSTALL_BINOP (op_pow, octave_scalar, octave_sparse_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_scalar, octave_sparse_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_scalar, octave_sparse_matrix, lt); + INSTALL_BINOP (op_le, octave_scalar, octave_sparse_matrix, le); + INSTALL_BINOP (op_eq, octave_scalar, octave_sparse_matrix, eq); + INSTALL_BINOP (op_ge, octave_scalar, octave_sparse_matrix, ge); + INSTALL_BINOP (op_gt, octave_scalar, octave_sparse_matrix, gt); + INSTALL_BINOP (op_ne, octave_scalar, octave_sparse_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_scalar, octave_sparse_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_scalar, octave_sparse_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_scalar, octave_sparse_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_scalar, octave_sparse_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_scalar, octave_sparse_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_scalar, octave_sparse_matrix, el_or); + + INSTALL_CATOP (octave_scalar, octave_sparse_matrix, s_sm); + + INSTALL_ASSIGNCONV (octave_scalar, octave_sparse_matrix, octave_matrix); + + INSTALL_WIDENOP (octave_scalar, octave_sparse_matrix, sparse_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sbm-b.cc b/src/OPERATORS/op-sbm-b.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sbm-b.cc @@ -0,0 +1,97 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-bool.h" +#include "ov-scalar.h" +#include "ops.h" + +#include "ov-re-sparse.h" + +// sparse bool matrix by bool ops. + +DEFBINOP_FN (ne, sparse_bool_matrix, bool, mx_el_ne) +DEFBINOP_FN (eq, sparse_bool_matrix, bool, mx_el_eq) + +DEFBINOP_FN (el_and, sparse_bool_matrix, bool, mx_el_and) +DEFBINOP_FN (el_or, sparse_bool_matrix, bool, mx_el_or) + +DEFCATOP (sbm_b, sparse_bool_matrix, bool) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_bool&); + + SparseBoolMatrix tmp (1, 1, v2.bool_value ()); + return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx)); +} + +DEFCATOP (sm_b, sparse_matrix, bool) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_bool&); + + SparseMatrix tmp (1, 1, v2.scalar_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFCATOP (sbm_s, sparse_bool_matrix, scalar) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_scalar&); + + SparseMatrix tmp (1, 1, v2.scalar_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_bool_matrix, bool) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_bool&); + + SparseBoolMatrix tmp (1, 1, v2.bool_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_sbm_b_ops (void) +{ + INSTALL_BINOP (op_eq, octave_sparse_bool_matrix, octave_bool, eq); + INSTALL_BINOP (op_ne, octave_sparse_bool_matrix, octave_bool, ne); + + INSTALL_BINOP (op_el_and, octave_sparse_bool_matrix, octave_bool, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_bool_matrix, octave_bool, el_or); + + INSTALL_CATOP (octave_sparse_bool_matrix, octave_bool, sbm_b); + INSTALL_CATOP (octave_sparse_bool_matrix, octave_scalar, sbm_s); + INSTALL_CATOP (octave_sparse_matrix, octave_bool, sm_b); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_bool_matrix, octave_bool, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sbm-bm.cc b/src/OPERATORS/op-sbm-bm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sbm-bm.cc @@ -0,0 +1,102 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-bool-mat.h" +#include "boolMatrix.h" +#include "ov-scalar.h" +#include "ops.h" + +#include "ov-re-sparse.h" +#include "smx-bm-sbm.h" +#include "smx-sbm-bm.h" + +// sparse bool matrix by bool matrix ops. + +DEFBINOP_FN (eq, sparse_bool_matrix, bool_matrix, mx_el_eq) +DEFBINOP_FN (ne, sparse_bool_matrix, bool_matrix, mx_el_ne) + +DEFBINOP_FN (el_and, sparse_bool_matrix, bool_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_bool_matrix, bool_matrix, mx_el_or) + +DEFCATOP (sbm_bm, sparse_bool_matrix, bool_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_bool_matrix&); + + SparseBoolMatrix tmp (v2.bool_matrix_value ()); + return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx)); +} + +DEFCATOP (sbm_m, sparse_bool_matrix, matrix) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_matrix&); + + SparseMatrix tmp (v2.matrix_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFCATOP (sm_bm, sparse_matrix, bool_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_bool_matrix&); + + SparseMatrix tmp (v2.matrix_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_bool_matrix, bool_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_bool_matrix&, const octave_bool_matrix&); + + v1.assign (idx, SparseBoolMatrix (v2.bool_matrix_value ())); + return octave_value (); +} + +void +install_sbm_bm_ops (void) +{ + INSTALL_BINOP (op_eq, octave_sparse_bool_matrix, octave_bool_matrix, eq); + INSTALL_BINOP (op_ne, octave_sparse_bool_matrix, octave_bool_matrix, ne); + + INSTALL_BINOP (op_el_and, octave_sparse_bool_matrix, octave_bool_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_bool_matrix, octave_bool_matrix, + el_or); + + INSTALL_CATOP (octave_sparse_bool_matrix, octave_bool_matrix, sbm_bm); + INSTALL_CATOP (octave_sparse_matrix, octave_bool_matrix, sm_bm); + INSTALL_CATOP (octave_sparse_bool_matrix, octave_matrix, sbm_m); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_bool_matrix, + octave_bool_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sbm-sbm.cc b/src/OPERATORS/op-sbm-sbm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sbm-sbm.cc @@ -0,0 +1,108 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-bool-mat.h" +#include "ov-scalar.h" +#include "ops.h" + +#include "ov-re-sparse.h" +#include "ov-bool-sparse.h" + +// unary sparse bool matrix ops. + +DEFUNOP_OP (not, sparse_bool_matrix, !) + +DEFUNOP (uplus, sparse_bool_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_bool_matrix&); + return octave_value (v.sparse_matrix_value ()); +} + +DEFUNOP (uminus, sparse_bool_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_bool_matrix&); + return octave_value ( - v.sparse_matrix_value ()); +} + +DEFUNOP (transpose, sparse_bool_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_bool_matrix&); + return octave_value (v.sparse_bool_matrix_value().transpose ()); +} + +// sparse bool matrix by sparse bool matrix ops. + +DEFBINOP_FN (eq, sparse_bool_matrix, sparse_bool_matrix, mx_el_eq) +DEFBINOP_FN (ne, sparse_bool_matrix, sparse_bool_matrix, mx_el_ne) +DEFBINOP_FN (el_and, sparse_bool_matrix, sparse_bool_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_bool_matrix, sparse_bool_matrix, mx_el_or) + +DEFNDCATOP_FN (sbm_sbm, sparse_bool_matrix, sparse_bool_matrix, + sparse_bool_matrix, sparse_bool_matrix, concat) +DEFNDCATOP_FN (sbm_sm, sparse_bool_matrix, sparse_matrix, sparse_matrix, + sparse_matrix, concat) +DEFNDCATOP_FN (sm_sbm, sparse_matrix, sparse_bool_matrix, sparse_matrix, + sparse_matrix, concat) + +DEFASSIGNOP_FN (assign, sparse_bool_matrix, sparse_bool_matrix, + assign) + +void +install_sbm_sbm_ops (void) +{ + INSTALL_UNOP (op_not, octave_sparse_bool_matrix, not); + INSTALL_UNOP (op_uplus, octave_sparse_bool_matrix, uplus); + INSTALL_UNOP (op_uminus, octave_sparse_bool_matrix, uminus); + INSTALL_UNOP (op_transpose, octave_sparse_bool_matrix, transpose); + INSTALL_UNOP (op_hermitian, octave_sparse_bool_matrix, transpose); + + INSTALL_BINOP (op_eq, octave_sparse_bool_matrix, + octave_sparse_bool_matrix, eq); + INSTALL_BINOP (op_ne, octave_sparse_bool_matrix, + octave_sparse_bool_matrix, ne); + + INSTALL_BINOP (op_el_and, octave_sparse_bool_matrix, + octave_sparse_bool_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_bool_matrix, + octave_sparse_bool_matrix, el_or); + + INSTALL_CATOP (octave_sparse_bool_matrix, octave_sparse_bool_matrix, + sbm_sbm); + INSTALL_CATOP (octave_sparse_bool_matrix, octave_sparse_matrix, sbm_sm); + INSTALL_CATOP (octave_sparse_matrix, octave_sparse_bool_matrix, sm_sbm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_bool_matrix, + octave_sparse_bool_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-cm.cc b/src/OPERATORS/op-scm-cm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-cm.cc @@ -0,0 +1,180 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-scm-cm.h" +#include "smx-cm-scm.h" +#include "ov-cx-sparse.h" + +// sparse complex matrix by complex matrix ops. + +DEFBINOP_OP (add, sparse_complex_matrix, complex_matrix, +) +DEFBINOP_OP (sub, sparse_complex_matrix, complex_matrix, -) + +DEFBINOP (mul, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + ComplexMatrix tmp (v1.complex_matrix_value ()); + + return octave_value ( tmp * v2.complex_matrix_value()); +} + +DEFBINOP (div, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + return xdiv (v1.complex_matrix_value (), v2.complex_matrix_value ()); +} + +DEFBINOPX (pow, sparse_complex_matrix, complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + return xleftdiv (v1.sparse_complex_matrix_value (), + v2.complex_matrix_value ()); +} + +DEFBINOP_FN (lt, sparse_complex_matrix, complex_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, complex_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_complex_matrix, complex_matrix, product) +DEFBINOP_FN (el_div, sparse_complex_matrix, complex_matrix, quotient) + +DEFBINOP (el_pow, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + return octave_value + (elem_xpow (v1.sparse_complex_matrix_value (), SparseComplexMatrix + (v2.complex_matrix_value ()))); +} + +DEFBINOP (el_ldiv, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + return octave_value (quotient (v2.complex_matrix_value (), + v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, complex_matrix, mx_el_or) + +DEFCATOP (scm_cm, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, + const octave_complex_matrix&); + SparseComplexMatrix tmp (v2.complex_matrix_value ()); + return octave_value + (v1.sparse_complex_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_complex_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, + const octave_complex_matrix&); + + SparseComplexMatrix tmp (v2.complex_matrix_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_scm_cm_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, + octave_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, + octave_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, + octave_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, + octave_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, + octave_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, + octave_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, + octave_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, + octave_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, + octave_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, + octave_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, + octave_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, + octave_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, + octave_complex_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, + octave_complex_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, + octave_complex_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, + octave_complex_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, + octave_complex_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, + octave_complex_matrix, el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, + octave_complex_matrix, scm_cm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, + octave_complex_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-cs.cc b/src/OPERATORS/op-scm-cs.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-cs.cc @@ -0,0 +1,183 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ov-complex.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-cx-sparse.h" + +// sparse complex matrix by complex scalar ops. + +DEFBINOP_OP (add, sparse_complex_matrix, complex, +) +DEFBINOP_OP (sub, sparse_complex_matrix, complex, -) +DEFBINOP_OP (mul, sparse_complex_matrix, complex, *) + +DEFBINOP (div, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex&); + + Complex d = v2.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = (v1.complex_matrix_value () / d); + } + else + retval = octave_value (v1.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP (pow, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex&); + return xpow (v1.complex_matrix_value (), v2.scalar_value ()); +} + +DEFBINOP (ldiv, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex&); + + SparseComplexMatrix m1 = v1.sparse_complex_matrix_value (); + ComplexMatrix m2 = ComplexMatrix (1, 1, v2.complex_value ()); + + return xleftdiv (m1, m2); +} + +DEFBINOP_FN (lt, sparse_complex_matrix, complex, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, complex, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, complex, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, complex, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, complex, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, complex, mx_el_ne) + +DEFBINOP_OP (el_mul, sparse_complex_matrix, complex, *) + +DEFBINOP (el_div, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex&); + + octave_value retval; + + Complex d = v2.complex_value (); + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.complex_matrix_value () / d); + } + else + retval = octave_value (v1.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_pow, sparse_complex_matrix, complex, elem_xpow) + +DEFBINOP (el_ldiv, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_complex&); + + return octave_value + (x_el_div (v2.complex_value (), v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, complex, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, complex, mx_el_or) + +DEFCATOP (scm_cs, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_complex&); + SparseComplexMatrix tmp (1, 1, v2.complex_value ()); + return octave_value + (v1.sparse_complex_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_complex_matrix, complex) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_complex&); + + SparseComplexMatrix tmp (1, 1, v2.complex_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_scm_cs_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, octave_complex, add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, octave_complex, sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, octave_complex, mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, octave_complex, div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, octave_complex, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, octave_complex, + ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, octave_complex, lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, octave_complex, le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, octave_complex, eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, octave_complex, ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, octave_complex, gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, octave_complex, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, octave_complex, + el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, octave_complex, + el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, octave_complex, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, octave_complex, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, octave_complex, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, octave_complex, + el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, octave_complex, scm_cs); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, octave_complex, + assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-m.cc b/src/OPERATORS/op-scm-m.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-m.cc @@ -0,0 +1,165 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-re-mat.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-scm-m.h" +#include "smx-m-scm.h" +#include "ov-cx-sparse.h" + +// sparse complex matrix by matrix ops. + +DEFBINOP_OP (add, sparse_complex_matrix, matrix, +) +DEFBINOP_OP (sub, sparse_complex_matrix, matrix, -) + +DEFBINOP (mul, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_matrix&); + + ComplexMatrix tmp (v1.complex_matrix_value ()); + + return octave_value ( tmp * v2.matrix_value()); +} + +DEFBINOP (div, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_matrix&); + + return xdiv (v1.complex_matrix_value (), v2.matrix_value ()); +} + +DEFBINOPX (pow, sparse_complex_matrix, matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_matrix&); + + return xleftdiv (v1.sparse_complex_matrix_value (), v2.matrix_value ()); +} + +DEFBINOP_FN (lt, sparse_complex_matrix, matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_complex_matrix, matrix, product) +DEFBINOP_FN (el_div, sparse_complex_matrix, matrix, quotient) + +DEFBINOP (el_pow, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_matrix&); + + return octave_value + (elem_xpow (v1.sparse_complex_matrix_value (), SparseMatrix + (v2.matrix_value ()))); +} + +DEFBINOP (el_ldiv, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_matrix&); + + return octave_value + (quotient (v2.matrix_value (), v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, matrix, mx_el_or) + +DEFCATOP (scm_m, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_matrix&); + SparseMatrix tmp (v2.matrix_value ()); + return octave_value + (v1.sparse_complex_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_complex_matrix, matrix) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_matrix&); + + SparseComplexMatrix tmp (v2.complex_matrix_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_scm_m_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, octave_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, octave_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, octave_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, octave_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, octave_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, octave_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, octave_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, octave_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, octave_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, octave_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, octave_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, octave_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, octave_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, octave_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, octave_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, octave_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, octave_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, octave_matrix, + el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, octave_matrix, scm_m); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, octave_matrix, + assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-s.cc b/src/OPERATORS/op-scm-s.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-s.cc @@ -0,0 +1,188 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ov-scalar.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-scm-s.h" +#include "smx-s-scm.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// sparse complex matrix by scalar ops. + +DEFBINOP_OP (add, sparse_complex_matrix, scalar, +) +DEFBINOP_OP (sub, sparse_complex_matrix, scalar, -) +DEFBINOP_OP (mul, sparse_complex_matrix, scalar, *) + +DEFBINOP (div, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_scalar&); + + double d = v2.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.complex_matrix_value () / d); + } + else + retval = octave_value (v1.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP (pow, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_scalar&); + + double tmp = v2.scalar_value (); + if (static_cast (tmp) == tmp) + return xpow (v1.sparse_complex_matrix_value (), tmp); + else + return xpow (v1.complex_matrix_value (), tmp); +} + +DEFBINOP (ldiv, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_scalar&); + + SparseComplexMatrix m1 = v1.sparse_complex_matrix_value (); + Matrix m2 = Matrix (1, 1, v2.scalar_value ()); + + return xleftdiv (m1, m2); +} + +DEFBINOP_FN (lt, sparse_complex_matrix, scalar, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, scalar, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, scalar, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, scalar, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, scalar, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, scalar, mx_el_ne) + +DEFBINOP_OP (el_mul, sparse_complex_matrix, scalar, *) + +DEFBINOP (el_div, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_scalar&); + + double d = v2.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.complex_matrix_value () / d); + } + else + retval = octave_value (v1.sparse_complex_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_pow, sparse_complex_matrix, scalar, elem_xpow) + +DEFBINOP (el_ldiv, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, const octave_scalar&); + + return octave_value + (x_el_div (v2.double_value (), v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, scalar, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, scalar, mx_el_or) + +DEFCATOP (scm_s, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_scalar&); + SparseComplexMatrix tmp (1, 1, v2.complex_value ()); + return octave_value + (v1.sparse_complex_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_complex_matrix, scalar) +{ + CAST_BINOP_ARGS (octave_sparse_complex_matrix&, const octave_scalar&); + + SparseComplexMatrix tmp (1, 1, v2.complex_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_scm_s_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, octave_scalar, add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, octave_scalar, sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, octave_scalar, mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, octave_scalar, div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, octave_scalar, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, octave_scalar, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, octave_scalar, lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, octave_scalar, le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, octave_scalar, eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, octave_scalar, ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, octave_scalar, gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, octave_scalar, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, octave_scalar, + el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, octave_scalar, + el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, octave_scalar, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, octave_scalar, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, octave_scalar, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, octave_scalar, + el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, octave_scalar, scm_s); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, octave_scalar, + assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-scm.cc b/src/OPERATORS/op-scm-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-scm.cc @@ -0,0 +1,196 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ops.h" + +#include "sparse-xdiv.h" +#include "sparse-xpow.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) +#pragma implementation +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-cx-mat.h" +#include "ov-typeinfo.h" +#include "ops.h" +#include "xdiv.h" +#include "xpow.h" + +// unary sparse complex matrix ops. + +DEFUNOP_OP (not, sparse_complex_matrix, !) +DEFUNOP_OP (uplus, sparse_complex_matrix, /* no-op */) +DEFUNOP_OP (uminus, sparse_complex_matrix, -) + +DEFUNOP (transpose, sparse_complex_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_complex_matrix&); + + return octave_value (v.sparse_complex_matrix_value().transpose ()); +} + +DEFUNOP (hermitian, sparse_complex_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_complex_matrix&); + + return octave_value (v.sparse_complex_matrix_value().hermitian ()); +} + +#if 0 +DEFUNOP (incr, sparse_complex_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_complex_matrix&); + + return octave_value (v.complex_matrix_value () .increment ()); +} + +DEFUNOP (decr, sparse_complex_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_complex_matrix&); + + return octave_value (v.complex_matrix_value () .decrement ()); +} +#endif + +// complex matrix by complex matrix ops. + +DEFBINOP_OP (add, sparse_complex_matrix, sparse_complex_matrix, +) +DEFBINOP_OP (sub, sparse_complex_matrix, sparse_complex_matrix, -) + +DEFBINOP_OP (mul, sparse_complex_matrix, sparse_complex_matrix, *) + +DEFBINOP_FN (div, sparse_complex_matrix, sparse_complex_matrix, xdiv) + +DEFBINOPX (pow, sparse_complex_matrix, sparse_complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP_FN (ldiv, sparse_complex_matrix, sparse_complex_matrix, xleftdiv) + +DEFBINOP_FN (lt, sparse_complex_matrix, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_complex_matrix, sparse_complex_matrix, product) +DEFBINOP_FN (el_div, sparse_complex_matrix, sparse_complex_matrix, quotient) +DEFBINOP_FN (el_pow, sparse_complex_matrix, sparse_complex_matrix, elem_xpow) + +DEFBINOP (el_ldiv, sparse_complex_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_sparse_complex_matrix&); + + return octave_value (quotient (v2.sparse_complex_matrix_value (), + v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, sparse_complex_matrix, mx_el_or) + +DEFCATOP_FN (scm_scm, sparse_complex_matrix, sparse_complex_matrix, concat) + +DEFASSIGNOP_FN (assign, sparse_complex_matrix, sparse_complex_matrix, assign) + +void +install_scm_scm_ops (void) +{ + INSTALL_UNOP (op_not, octave_sparse_complex_matrix, not); + INSTALL_UNOP (op_uplus, octave_sparse_complex_matrix, uplus); + INSTALL_UNOP (op_uminus, octave_sparse_complex_matrix, uminus); + INSTALL_UNOP (op_transpose, octave_sparse_complex_matrix, transpose); + INSTALL_UNOP (op_hermitian, octave_sparse_complex_matrix, hermitian); + +#if 0 + INSTALL_NCUNOP (op_incr, octave_sparse_complex_matrix, incr); + INSTALL_NCUNOP (op_decr, octave_sparse_complex_matrix, decr); +#endif + + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, + octave_sparse_complex_matrix, scm_scm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, + octave_sparse_complex_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-scm-sm.cc b/src/OPERATORS/op-scm-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-scm-sm.cc @@ -0,0 +1,133 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ops.h" + +#include "sparse-xdiv.h" +#include "sparse-xpow.h" +#include "smx-sm-scm.h" +#include "smx-scm-sm.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// sparse complex matrix by sparse matrix ops. + +DEFBINOP_OP (add, sparse_complex_matrix, sparse_matrix, +) +DEFBINOP_OP (sub, sparse_complex_matrix, sparse_matrix, -) + +DEFBINOP_OP (mul, sparse_complex_matrix, sparse_matrix, *) + +DEFBINOP_FN (div, sparse_complex_matrix, sparse_matrix, xdiv) + +DEFBINOPX (pow, sparse_complex_matrix, sparse_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP_FN (ldiv, sparse_complex_matrix, sparse_matrix, xleftdiv) + +DEFBINOP_FN (lt, sparse_complex_matrix, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_complex_matrix, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_complex_matrix, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_complex_matrix, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_complex_matrix, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_complex_matrix, sparse_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_complex_matrix, sparse_matrix, product) +DEFBINOP_FN (el_div, sparse_complex_matrix, sparse_matrix, quotient) +DEFBINOP_FN (el_pow, sparse_complex_matrix, sparse_matrix, elem_xpow) + +DEFBINOP (el_ldiv, sparse_complex_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_complex_matrix&, + const octave_sparse_matrix&); + + return octave_value + (quotient (v2.sparse_matrix_value (), v1.sparse_complex_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_complex_matrix, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_complex_matrix, sparse_matrix, mx_el_or) + +DEFCATOP_FN (scm_sm, sparse_complex_matrix, sparse_matrix, concat) + +DEFASSIGNOP_FN (assign, sparse_complex_matrix, sparse_matrix, assign) + +void +install_scm_sm_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_complex_matrix, octave_sparse_matrix, + add); + INSTALL_BINOP (op_sub, octave_sparse_complex_matrix, octave_sparse_matrix, + sub); + INSTALL_BINOP (op_mul, octave_sparse_complex_matrix, octave_sparse_matrix, + mul); + INSTALL_BINOP (op_div, octave_sparse_complex_matrix, octave_sparse_matrix, + div); + INSTALL_BINOP (op_pow, octave_sparse_complex_matrix, octave_sparse_matrix, + pow); + INSTALL_BINOP (op_ldiv, octave_sparse_complex_matrix, octave_sparse_matrix, + ldiv); + INSTALL_BINOP (op_lt, octave_sparse_complex_matrix, octave_sparse_matrix, + lt); + INSTALL_BINOP (op_le, octave_sparse_complex_matrix, octave_sparse_matrix, + le); + INSTALL_BINOP (op_eq, octave_sparse_complex_matrix, octave_sparse_matrix, + eq); + INSTALL_BINOP (op_ge, octave_sparse_complex_matrix, octave_sparse_matrix, + ge); + INSTALL_BINOP (op_gt, octave_sparse_complex_matrix, octave_sparse_matrix, + gt); + INSTALL_BINOP (op_ne, octave_sparse_complex_matrix, octave_sparse_matrix, + ne); + INSTALL_BINOP (op_el_mul, octave_sparse_complex_matrix, + octave_sparse_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_complex_matrix, + octave_sparse_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_complex_matrix, + octave_sparse_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_complex_matrix, + octave_sparse_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_complex_matrix, + octave_sparse_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_complex_matrix, + octave_sparse_matrix, el_or); + + INSTALL_CATOP (octave_sparse_complex_matrix, octave_sparse_matrix, scm_sm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_complex_matrix, + octave_sparse_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-cm.cc b/src/OPERATORS/op-sm-cm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-cm.cc @@ -0,0 +1,163 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-cx-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-sm-cm.h" +#include "smx-cm-sm.h" +#include "ov-re-sparse.h" + +// sparse matrix by complex matrix ops. + +DEFBINOP_OP (add, sparse_matrix, complex_matrix, +) +DEFBINOP_OP (sub, sparse_matrix, complex_matrix, -) + +DEFBINOP (mul, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_complex_matrix&); + + Matrix tmp (v1.matrix_value ()); + + return octave_value ( tmp * v2.complex_matrix_value()); +} + +DEFBINOP (div, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_complex_matrix&); + + return xdiv (v1.matrix_value (), v2.complex_matrix_value ()); +} + +DEFBINOPX (pow, sparse_matrix, complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_complex_matrix&); + + return xleftdiv (v1.sparse_matrix_value (), v2.complex_matrix_value ()); +} + +DEFBINOP_FN (lt, sparse_matrix, complex_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, complex_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_matrix, complex_matrix, product) +DEFBINOP_FN (el_div, sparse_matrix, complex_matrix, quotient) + +DEFBINOP (el_pow, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_complex_matrix&); + + return octave_value + (elem_xpow (v1.sparse_matrix_value (), SparseComplexMatrix + (v2.complex_matrix_value ()))); +} + +DEFBINOP (el_ldiv, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_complex_matrix&); + + return octave_value + (quotient (v2.complex_matrix_value (), v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, complex_matrix, mx_el_or) + +DEFCATOP (sm_cm, sparse_matrix, complex_matrix) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_complex_matrix&); + SparseComplexMatrix tmp (v2.complex_matrix_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_sparse_matrix&); + return new octave_complex_matrix (v.complex_matrix_value ()); +} + +void +install_sm_cm_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_complex_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_complex_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_complex_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_complex_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_complex_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_complex_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_complex_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_complex_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_complex_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_complex_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_complex_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_complex_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, octave_complex_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, octave_complex_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, octave_complex_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, octave_complex_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, octave_complex_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, octave_complex_matrix, + el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_complex_matrix, sm_cm); + + INSTALL_ASSIGNCONV (octave_sparse_matrix, octave_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_sparse_matrix, octave_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-cs.cc b/src/OPERATORS/op-sm-cs.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-cs.cc @@ -0,0 +1,163 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-complex.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" +#include "smx-sm-cs.h" +#include "smx-cs-sm.h" + +// sparse matrix by scalar ops. + +DEFBINOP_OP (add, sparse_matrix, complex, +) +DEFBINOP_OP (sub, sparse_matrix, complex, -) +DEFBINOP_OP (mul, sparse_matrix, complex, *) + +DEFBINOP (div, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_complex&); + + Complex d = v2.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.matrix_value () / d); + } + else + retval = octave_value (v1.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP (pow, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_complex&); + return xpow (v1.matrix_value (), v2.complex_value ()); +} + +DEFBINOP (ldiv, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_complex&); + + SparseMatrix m1 = v1.sparse_matrix_value (); + ComplexMatrix m2 = ComplexMatrix (1, 1, v2.complex_value ()); + + return xleftdiv (m1, m2); +} + +DEFBINOP_FN (lt, sparse_matrix, complex, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, complex, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, complex, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, complex, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, complex, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, complex, mx_el_ne) + +DEFBINOP_OP (el_mul, sparse_matrix, complex, *) + +DEFBINOP (el_div, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_complex&); + + Complex d = v2.complex_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.matrix_value () / d); + } + else + retval = octave_value (v1.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_pow, sparse_matrix, complex, elem_xpow) + +DEFBINOP (el_ldiv, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_complex&); + + return octave_value (x_el_div (v2.complex_value (), + v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, complex, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, complex, mx_el_or) + +DEFCATOP (sm_cs, sparse_matrix, complex) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_complex&); + SparseComplexMatrix tmp (1, 1, v2.complex_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +void +install_sm_cs_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_complex, add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_complex, sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_complex, mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_complex, div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_complex, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_complex, ldiv); + + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_complex, lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_complex, le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_complex, eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_complex, ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_complex, gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_complex, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, octave_complex, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, octave_complex, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, octave_complex, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, octave_complex, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, octave_complex, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, octave_complex, el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_complex, sm_cs); + + INSTALL_ASSIGNCONV (octave_sparse_matrix, octave_complex, + octave_sparse_complex_matrix); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-m.cc b/src/OPERATORS/op-sm-m.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-m.cc @@ -0,0 +1,151 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-re-mat.h" +#include "ops.h" +#include "xdiv.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "smx-sm-m.h" +#include "smx-m-sm.h" +#include "ov-re-sparse.h" + +// sparse matrix by matrix ops. + +DEFBINOP_OP (add, sparse_matrix, matrix, +) +DEFBINOP_OP (sub, sparse_matrix, matrix, -) + +DEFBINOP (mul, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_matrix&); + + Matrix tmp (v1.matrix_value ()); + + return octave_value ( tmp * v2.matrix_value()); +} + +DEFBINOP (div, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_matrix&); + + return xdiv (v1.matrix_value (), v2.matrix_value ()); +} + +DEFBINOPX (pow, sparse_matrix, matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP (ldiv, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_matrix&); + + return xleftdiv (v1.sparse_matrix_value (), v2.matrix_value ()); +} + + +DEFBINOP_FN (lt, sparse_matrix, matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_matrix, matrix, product) +DEFBINOP_FN (el_div, sparse_matrix, matrix, quotient) + +DEFBINOP (el_pow, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_matrix&); + + return octave_value (elem_xpow (v1.sparse_matrix_value (), + SparseMatrix (v2.matrix_value ()))); +} + +DEFBINOP (el_ldiv, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_matrix&); + + return octave_value + (quotient (v2.matrix_value (), v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, matrix, mx_el_or) + +DEFCATOP (sm_m, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_matrix&); + SparseMatrix tmp (v2.matrix_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_matrix, matrix) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_matrix&); + + SparseMatrix tmp (v2.matrix_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_sm_m_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, octave_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, octave_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, octave_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, octave_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, octave_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, octave_matrix, el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_matrix, sm_m); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_matrix, octave_matrix, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-s.cc b/src/OPERATORS/op-sm-s.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-s.cc @@ -0,0 +1,173 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-scalar.h" +#include "ops.h" +#include "xpow.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-re-sparse.h" + +// sparse matrix by scalar ops. + +DEFBINOP_OP (add, sparse_matrix, scalar, +) +DEFBINOP_OP (sub, sparse_matrix, scalar, -) +DEFBINOP_OP (mul, sparse_matrix, scalar, *) + +DEFBINOP (div, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_scalar&); + + double d = v2.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.matrix_value () / d); + } + else + retval = octave_value (v1.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP (pow, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_scalar&); + + double tmp = v2.scalar_value (); + if (static_cast (tmp) == tmp) + return xpow (v1.sparse_matrix_value (), tmp); + else + return xpow (v1.matrix_value (), tmp); +} + +DEFBINOP (ldiv, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_scalar&); + + SparseMatrix m1 = v1.sparse_matrix_value (); + Matrix m2 = Matrix (1, 1, v2.scalar_value ()); + + return xleftdiv (m1, m2); +} + +DEFBINOP_FN (lt, sparse_matrix, scalar, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, scalar, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, scalar, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, scalar, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, scalar, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, scalar, mx_el_ne) + +DEFBINOP_OP (el_mul, sparse_matrix, scalar, *) + +DEFBINOP (el_div, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_scalar&); + + double d = v2.double_value (); + octave_value retval; + + if (d == 0.0) + { + gripe_divide_by_zero (); + + retval = octave_value (v1.matrix_value () / d); + } + else + retval = octave_value (v1.sparse_matrix_value () / d); + + return retval; +} + +DEFBINOP_FN (el_pow, sparse_matrix, scalar, elem_xpow) + +DEFBINOP (el_ldiv, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_scalar&); + + return octave_value + (x_el_div (v2.complex_value (), v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, scalar, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, scalar, mx_el_or) + +DEFCATOP (sm_s, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_scalar&); + SparseMatrix tmp (1, 1, v2.scalar_value ()); + return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx)); +} + +DEFASSIGNOP (assign, sparse_matrix, scalar) +{ + CAST_BINOP_ARGS (octave_sparse_matrix&, const octave_scalar&); + + SparseMatrix tmp (1, 1, v2.scalar_value ()); + v1.assign (idx, tmp); + return octave_value (); +} + +void +install_sm_s_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_scalar, add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_scalar, sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_scalar, mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_scalar, div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_scalar, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_scalar, ldiv); + + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_scalar, lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_scalar, le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_scalar, eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_scalar, ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_scalar, gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_scalar, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, octave_scalar, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, octave_scalar, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, octave_scalar, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, octave_scalar, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, octave_scalar, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, octave_scalar, el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_scalar, sm_s); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_matrix, octave_scalar, assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-scm.cc b/src/OPERATORS/op-sm-scm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-scm.cc @@ -0,0 +1,140 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ops.h" + +#include "sparse-xdiv.h" +#include "sparse-xpow.h" +#include "smx-sm-scm.h" +#include "smx-scm-sm.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +// sparse matrix by sparse complex matrix ops. + +DEFBINOP_OP (add, sparse_matrix, sparse_complex_matrix, +) +DEFBINOP_OP (sub, sparse_matrix, sparse_complex_matrix, -) + +DEFBINOP_OP (mul, sparse_matrix, sparse_complex_matrix, *) + +DEFBINOP_FN (div, sparse_matrix, sparse_complex_matrix, xdiv) + +DEFBINOPX (pow, sparse_matrix, sparse_complex_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP_FN (ldiv, sparse_matrix, sparse_complex_matrix, xleftdiv) + +DEFBINOP_FN (lt, sparse_matrix, sparse_complex_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, sparse_complex_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, sparse_complex_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, sparse_complex_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, sparse_complex_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, sparse_complex_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_matrix, sparse_complex_matrix, product) +DEFBINOP_FN (el_div, sparse_matrix, sparse_complex_matrix, quotient) +DEFBINOP_FN (el_pow, sparse_matrix, sparse_complex_matrix, elem_xpow) + +DEFBINOP (el_ldiv, sparse_matrix, sparse_complex_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, + const octave_sparse_complex_matrix&); + + return octave_value + (quotient (v2.sparse_complex_matrix_value (), v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, sparse_complex_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, sparse_complex_matrix, mx_el_or) + +DEFCATOP_FN (sm_scm, sparse_matrix, sparse_complex_matrix, concat) + +DEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix) +{ + CAST_CONV_ARG (const octave_sparse_matrix&); + return new octave_sparse_complex_matrix (v.sparse_complex_matrix_value ()); +} + +void +install_sm_scm_ops (void) +{ + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_sparse_complex_matrix, + add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_sparse_complex_matrix, + sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_sparse_complex_matrix, + mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_sparse_complex_matrix, + div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_sparse_complex_matrix, + pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_sparse_complex_matrix, + ldiv); + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_sparse_complex_matrix, + lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_sparse_complex_matrix, + le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_sparse_complex_matrix, + eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_sparse_complex_matrix, + ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_sparse_complex_matrix, + gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_sparse_complex_matrix, + ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, + octave_sparse_complex_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, + octave_sparse_complex_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, + octave_sparse_complex_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, + octave_sparse_complex_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, + octave_sparse_complex_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, + octave_sparse_complex_matrix, el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_sparse_complex_matrix, sm_scm); + + INSTALL_ASSIGNCONV (octave_sparse_matrix, octave_sparse_complex_matrix, + octave_sparse_complex_matrix); + + INSTALL_WIDENOP (octave_sparse_matrix, octave_sparse_complex_matrix, + sparse_complex_matrix_conv); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-sm-sm.cc b/src/OPERATORS/op-sm-sm.cc new file mode 100644 --- /dev/null +++ b/src/OPERATORS/op-sm-sm.cc @@ -0,0 +1,135 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gripes.h" +#include "oct-obj.h" +#include "ov.h" +#include "ov-typeinfo.h" +#include "ov-re-mat.h" +#include "ops.h" + +#include "sparse-xpow.h" +#include "sparse-xdiv.h" +#include "ov-re-sparse.h" + +// sparse matrix unary ops. + +DEFUNOP_OP (not, sparse_matrix, !) +DEFUNOP_OP (uplus, sparse_matrix, /* no-op */) +DEFUNOP_OP (uminus, sparse_matrix, -) + +DEFUNOP (transpose, sparse_matrix) +{ + CAST_UNOP_ARG (const octave_sparse_matrix&); + return octave_value (v.sparse_matrix_value().transpose ()); +} + +// sparse matrix by sparse matrix ops. + +DEFBINOP_OP (add, sparse_matrix, sparse_matrix, +) +DEFBINOP_OP (sub, sparse_matrix, sparse_matrix, -) +DEFBINOP_OP (mul, sparse_matrix, sparse_matrix, *) + +DEFBINOP_FN (div, sparse_matrix, sparse_matrix, xdiv) + +DEFBINOPX (pow, sparse_matrix, sparse_matrix) +{ + error ("can't do A ^ B for A and B both matrices"); + return octave_value (); +} + +DEFBINOP_FN (ldiv, sparse_matrix, sparse_matrix, xleftdiv) + +DEFBINOP_FN (lt, sparse_matrix, sparse_matrix, mx_el_lt) +DEFBINOP_FN (le, sparse_matrix, sparse_matrix, mx_el_le) +DEFBINOP_FN (eq, sparse_matrix, sparse_matrix, mx_el_eq) +DEFBINOP_FN (ge, sparse_matrix, sparse_matrix, mx_el_ge) +DEFBINOP_FN (gt, sparse_matrix, sparse_matrix, mx_el_gt) +DEFBINOP_FN (ne, sparse_matrix, sparse_matrix, mx_el_ne) + +DEFBINOP_FN (el_mul, sparse_matrix, sparse_matrix, product) +DEFBINOP_FN (el_div, sparse_matrix, sparse_matrix, quotient) + +DEFBINOP_FN (el_pow, sparse_matrix, sparse_matrix, elem_xpow) + +DEFBINOP (el_ldiv, sparse_matrix, sparse_matrix) +{ + CAST_BINOP_ARGS (const octave_sparse_matrix&, const octave_sparse_matrix&); + return octave_value + (quotient (v2.sparse_matrix_value (), v1.sparse_matrix_value ())); +} + +DEFBINOP_FN (el_and, sparse_matrix, sparse_matrix, mx_el_and) +DEFBINOP_FN (el_or, sparse_matrix, sparse_matrix, mx_el_or) + +DEFCATOP_FN (sm_sm, sparse_matrix, sparse_matrix, concat) + +DEFASSIGNOP_FN (assign, sparse_matrix, sparse_matrix, assign) + +void +install_sm_sm_ops (void) +{ + INSTALL_UNOP (op_not, octave_sparse_matrix, not); + INSTALL_UNOP (op_uplus, octave_sparse_matrix, uplus); + INSTALL_UNOP (op_uminus, octave_sparse_matrix, uminus); + INSTALL_UNOP (op_transpose, octave_sparse_matrix, transpose); + INSTALL_UNOP (op_hermitian, octave_sparse_matrix, transpose); + + INSTALL_BINOP (op_add, octave_sparse_matrix, octave_sparse_matrix, add); + INSTALL_BINOP (op_sub, octave_sparse_matrix, octave_sparse_matrix, sub); + INSTALL_BINOP (op_mul, octave_sparse_matrix, octave_sparse_matrix, mul); + INSTALL_BINOP (op_div, octave_sparse_matrix, octave_sparse_matrix, div); + INSTALL_BINOP (op_pow, octave_sparse_matrix, octave_sparse_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_sparse_matrix, octave_sparse_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_sparse_matrix, octave_sparse_matrix, lt); + INSTALL_BINOP (op_le, octave_sparse_matrix, octave_sparse_matrix, le); + INSTALL_BINOP (op_eq, octave_sparse_matrix, octave_sparse_matrix, eq); + INSTALL_BINOP (op_ge, octave_sparse_matrix, octave_sparse_matrix, ge); + INSTALL_BINOP (op_gt, octave_sparse_matrix, octave_sparse_matrix, gt); + INSTALL_BINOP (op_ne, octave_sparse_matrix, octave_sparse_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_sparse_matrix, octave_sparse_matrix, + el_mul); + INSTALL_BINOP (op_el_div, octave_sparse_matrix, octave_sparse_matrix, + el_div); + INSTALL_BINOP (op_el_pow, octave_sparse_matrix, octave_sparse_matrix, + el_pow); + INSTALL_BINOP (op_el_ldiv, octave_sparse_matrix, octave_sparse_matrix, + el_ldiv); + INSTALL_BINOP (op_el_and, octave_sparse_matrix, octave_sparse_matrix, + el_and); + INSTALL_BINOP (op_el_or, octave_sparse_matrix, octave_sparse_matrix, + el_or); + + INSTALL_CATOP (octave_sparse_matrix, octave_sparse_matrix, sm_sm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_sparse_matrix, octave_sparse_matrix, + assign); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/OPERATORS/op-str-m.cc b/src/OPERATORS/op-str-m.cc --- a/src/OPERATORS/op-str-m.cc +++ b/src/OPERATORS/op-str-m.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-str-s.cc b/src/OPERATORS/op-str-s.cc --- a/src/OPERATORS/op-str-s.cc +++ b/src/OPERATORS/op-str-s.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-str-str.cc b/src/OPERATORS/op-str-str.cc --- a/src/OPERATORS/op-str-str.cc +++ b/src/OPERATORS/op-str-str.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-struct.cc b/src/OPERATORS/op-struct.cc --- a/src/OPERATORS/op-struct.cc +++ b/src/OPERATORS/op-struct.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-ui16-ui16.cc b/src/OPERATORS/op-ui16-ui16.cc --- a/src/OPERATORS/op-ui16-ui16.cc +++ b/src/OPERATORS/op-ui16-ui16.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-ui32-ui32.cc b/src/OPERATORS/op-ui32-ui32.cc --- a/src/OPERATORS/op-ui32-ui32.cc +++ b/src/OPERATORS/op-ui32-ui32.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-ui64-ui64.cc b/src/OPERATORS/op-ui64-ui64.cc --- a/src/OPERATORS/op-ui64-ui64.cc +++ b/src/OPERATORS/op-ui64-ui64.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/OPERATORS/op-ui8-ui8.cc b/src/OPERATORS/op-ui8-ui8.cc --- a/src/OPERATORS/op-ui8-ui8.cc +++ b/src/OPERATORS/op-ui8-ui8.cc @@ -20,10 +20,6 @@ */ -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/data.cc b/src/data.cc --- a/src/data.cc +++ b/src/data.cc @@ -537,7 +537,7 @@ else { ColumnVector v = m.diag (); - if (v.capacity () > 0) + if (v.numel () > 0) retval = v; } } @@ -560,7 +560,7 @@ else { ComplexColumnVector v = cm.diag (); - if (v.capacity () > 0) + if (v.numel () > 0) retval = v; } } @@ -729,16 +729,26 @@ octave_value tmp; bool any_strings = false; bool all_strings = true; + bool first_non_empty_arg = true; for (int i = 1; i < n_args; i++) - if (args(i).is_string ()) - any_strings = true; - else - all_strings = false; - + if (! args (i).all_zero_dims ()) + { + if (first_non_empty_arg) + { + first_non_empty_arg = false; + tmp = args (i); + } + + if (args(i).is_string ()) + any_strings = true; + else + all_strings = false; + } + if (all_strings) tmp = octave_value (charNDArray (dv, Vstring_fill_char), true); else - tmp = args(1).resize (dim_vector (0,0)).resize (dv); + tmp = tmp.resize (dim_vector (0,0)).resize (dv); if (error_state) return retval; diff --git a/src/ls-mat5.cc b/src/ls-mat5.cc --- a/src/ls-mat5.cc +++ b/src/ls-mat5.cc @@ -164,7 +164,7 @@ template void -read_mat5_integer_data (std::istream& is, T &m, int count, bool swap, +read_mat5_integer_data (std::istream& is, T *m, int count, bool swap, mat5_data_type type) { @@ -188,33 +188,27 @@ switch (type) { case miINT8: - READ_INTEGER_DATA (signed char, swap, m.fortran_vec (), 1, - count, is); + READ_INTEGER_DATA (signed char, swap, m, 1, count, is); break; case miUINT8: - READ_INTEGER_DATA (unsigned char, swap, m.fortran_vec (), 1, - count, is); + READ_INTEGER_DATA (unsigned char, swap, m, 1, count, is); break; case miINT16: - READ_INTEGER_DATA (signed TWO_BYTE_INT, swap, m.fortran_vec (), 2, - count, is); + READ_INTEGER_DATA (signed TWO_BYTE_INT, swap, m, 2, count, is); break; case miUINT16: - READ_INTEGER_DATA (unsigned TWO_BYTE_INT, swap, m.fortran_vec (), 2, - count, is); + READ_INTEGER_DATA (unsigned TWO_BYTE_INT, swap, m, 2, count, is); break; case miINT32: - READ_INTEGER_DATA (signed FOUR_BYTE_INT, swap, m.fortran_vec (), 4, - count, is); + READ_INTEGER_DATA (signed FOUR_BYTE_INT, swap, m, 4, count, is); break; case miUINT32: - READ_INTEGER_DATA (unsigned FOUR_BYTE_INT, swap, m.fortran_vec (), 4, - count, is); + READ_INTEGER_DATA (unsigned FOUR_BYTE_INT, swap, m, 4, count, is); break; case miSINGLE: @@ -226,15 +220,13 @@ case miINT64: #ifdef EIGHT_BYTE_INT - READ_INTEGER_DATA (signed EIGHT_BYTE_INT, swap, m.fortran_vec (), 8, - count, is); + READ_INTEGER_DATA (signed EIGHT_BYTE_INT, swap, m, 8, count, is); #endif break; case miUINT64: #ifdef EIGHT_BYTE_INT - READ_INTEGER_DATA (unsigned EIGHT_BYTE_INT, swap, m.fortran_vec (), 8, - count, is); + READ_INTEGER_DATA (unsigned EIGHT_BYTE_INT, swap, m, 8, count, is); #endif break; @@ -247,28 +239,32 @@ } -template void read_mat5_integer_data (std::istream& is, int8NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_int8 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, int16NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_int16 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, int32NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_int32 *m, + int count, bool swap, + mat5_data_type type); +template void read_mat5_integer_data (std::istream& is, octave_int64 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, int64NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_uint8 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, uint8NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_uint16 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, uint16NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_uint32 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, uint32NDArray &m, +template void read_mat5_integer_data (std::istream& is, octave_uint64 *m, int count, bool swap, mat5_data_type type); -template void read_mat5_integer_data (std::istream& is, uint64NDArray &m, + +template void read_mat5_integer_data (std::istream& is, int *m, int count, bool swap, mat5_data_type type); @@ -286,7 +282,7 @@ \ int n = re.length (); \ tmp_pos = is.tellg (); \ - read_mat5_integer_data (is, re, n, swap, \ + read_mat5_integer_data (is, re.fortran_vec (), n, swap, \ (enum mat5_data_type) type); \ \ if (! is || error_state) \ @@ -401,7 +397,7 @@ bool imag; bool logicalvar; enum arrayclasstype arrayclass; - FOUR_BYTE_INT junk; + FOUR_BYTE_INT nnz; FOUR_BYTE_INT flags; dim_vector dims; int len; @@ -448,7 +444,7 @@ global = (flags & 0x0400) != 0; // global variable? logicalvar = (flags & 0x0200) != 0; // we don't use this yet arrayclass = (arrayclasstype)(flags & 0xff); - read_int (is, swap, junk); // an "undefined" entry + read_int (is, swap, nnz); // number of non-zero in sparse // dimensions array subelement { @@ -531,8 +527,124 @@ goto skip_ahead; case mxSPARSE_CLASS: - warning ("load: sparse arrays are not implemented"); - goto skip_ahead; + { + int nr = dims(0); + int nc = dims(1); + SparseMatrix sm; + SparseComplexMatrix scm; + NDArray re; + int *ridx; + int *cidx; + double *data; + + // Setup return value + if (imag) + { + scm = SparseComplexMatrix (nr, nc, nnz); + ridx = scm.ridx (); + cidx = scm.cidx (); + re = NDArray (dim_vector (static_cast (nnz))); + data = re.fortran_vec (); + } + else + { + sm = SparseMatrix (nr, nc, nnz); + ridx = sm.ridx (); + cidx = sm.cidx (); + data = sm.data (); + } + + // row indices + std::streampos tmp_pos; + + if (read_mat5_tag (is, swap, type, len)) + { + error ("load: reading sparse row data for `%s'", retval.c_str ()); + goto data_read_error; + } + + tmp_pos = is.tellg (); + + read_mat5_integer_data (is, ridx, nnz, swap, + (enum mat5_data_type) type); + + if (! is || error_state) + { + error ("load: reading sparse row data for `%s'", retval.c_str ()); + goto data_read_error; + } + + is.seekg (tmp_pos + static_cast (PAD (len))); + + // col indices + if (read_mat5_tag (is, swap, type, len)) + { + error ("load: reading sparse column data for `%s'", retval.c_str ()); + goto data_read_error; + } + + tmp_pos = is.tellg (); + + read_mat5_integer_data (is, cidx, nc + 1, swap, + (enum mat5_data_type) type); + + if (! is || error_state) + { + error ("load: reading sparse column data for `%s'", retval.c_str ()); + goto data_read_error; + } + + is.seekg (tmp_pos + static_cast (PAD (len))); + + // real data subelement + if (read_mat5_tag (is, swap, type, len)) + { + error ("load: reading sparse matrix data for `%s'", retval.c_str ()); + goto data_read_error; + } + + tmp_pos = is.tellg (); + read_mat5_binary_data (is, data, nnz, swap, + (enum mat5_data_type) type, flt_fmt); + + if (! is || error_state) + { + error ("load: reading sparse matrix data for `%s'", retval.c_str ()); + goto data_read_error; + } + + is.seekg (tmp_pos + static_cast (PAD (len))); + + // imaginary data subelement + if (imag) + { + NDArray im (dim_vector (static_cast (nnz))); + + if (read_mat5_tag (is, swap, type, len)) + { + error ("load: reading sparse matrix data for `%s'", retval.c_str ()); + goto data_read_error; + } + + read_mat5_binary_data (is, im.fortran_vec (), nnz, swap, + (enum mat5_data_type) type, flt_fmt); + + if (! is || error_state) + { + error ("load: reading imaginary sparse matrix data for `%s'", + retval.c_str ()); + goto data_read_error; + } + + for (int i = 0; i < nnz; i++) + scm.xdata (i) = Complex (re (i), im (i)); + + tc = scm; + } + else + tc = sm; + } + break; case mxFUNCTION_CLASS: warning ("load: function handles are not implemented"); @@ -913,9 +1025,8 @@ template void -write_mat5_integer_data (std::ostream& os, const T& m, int size) +write_mat5_integer_data (std::ostream& os, const T *m, int size, int nel) { - int nel = m.nelem (); mat5_data_type mst; unsigned len; @@ -927,10 +1038,10 @@ case 2: mst = miUINT16; break; - case 3: + case 4: mst = miUINT32; break; - case 4: + case 8: mst = miUINT64; break; case -1: @@ -941,11 +1052,11 @@ mst = miINT16; size = - size; break; - case -3: + case -4: mst = miINT32; size = - size; break; - case -4: + case -8: default: mst = miINT64; size = - size; @@ -955,7 +1066,7 @@ len = nel*size; write_mat5_tag (os, mst, len); - os.write (X_CAST(char *, m.data ()), len); + os.write (X_CAST(char *, m), len); if (PAD (len) > len) { @@ -964,22 +1075,24 @@ } } -template void write_mat5_integer_data (std::ostream& os, - const int8NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const int16NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const int32NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const int64NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const uint8NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const uint16NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const uint32NDArray &m, int size); -template void write_mat5_integer_data (std::ostream& os, - const uint64NDArray &m, int size); +template void write_mat5_integer_data (std::ostream& os, const octave_int8 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_int16 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_int32 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_int64 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_uint8 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_uint16 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_uint32 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const octave_uint64 *m, + int size, int nel); +template void write_mat5_integer_data (std::ostream& os, const int *m, + int size, int nel); // Write out cell element values in the cell array to OS, preceded by // the appropriate tag. @@ -1011,7 +1124,7 @@ bool mark_as_global, bool save_as_floats) { FOUR_BYTE_INT flags=0; - FOUR_BYTE_INT junk=0; + FOUR_BYTE_INT nnz=0; std::streampos fixup, contin; std::string cname = tc.class_name (); @@ -1046,6 +1159,20 @@ flags |= mxUINT32_CLASS; else if (cname == "uint64") flags |= mxUINT64_CLASS; + else if (cname == "sparse") + { + flags |= mxSPARSE_CLASS; + if (tc.is_complex_type ()) + { + SparseComplexMatrix scm = tc.sparse_complex_matrix_value (); + nnz = scm.nnz (); + } + else + { + SparseMatrix sm = tc.sparse_matrix_value (); + nnz = sm.nnz (); + } + } else if (tc.is_real_scalar ()) flags |= mxDOUBLE_CLASS; else if (tc.is_real_matrix () || tc.is_range ()) @@ -1065,7 +1192,7 @@ } os.write ((char *)&flags, 4); - os.write ((char *)&junk, 4); + os.write ((char *)&nnz, 4); { dim_vector dv = tc.dims (); @@ -1128,53 +1255,93 @@ if (paddedlength > len) os.write ((char *)buf, paddedlength - len); } + else if (cname == "sparse") + { + if (tc.is_complex_type ()) + { + SparseComplexMatrix m = tc.sparse_complex_matrix_value (); + int nc = m.cols (); + + write_mat5_integer_data (os, m.ridx (), - sizeof(int), nnz); + write_mat5_integer_data (os, m.cidx (), - sizeof(int), nc + 1); + + NDArray buf (dim_vector (nnz, 1)); + + for (int i = 0; i < nnz; i++) + buf (i) = ::real (m.data (i)); + + write_mat5_array (os, buf, save_as_floats); + + for (int i = 0; i < nnz; i++) + buf (i) = ::imag (m.data (i)); + + write_mat5_array (os, buf, save_as_floats); + } + else + { + SparseMatrix m = tc.sparse_matrix_value (); + int nc = m.cols (); + + write_mat5_integer_data (os, m.ridx (), - sizeof(int), nnz); + write_mat5_integer_data (os, m.cidx (), - sizeof(int), nc + 1); + + // XXX FIXME XXX + // Is there a way to easily do without this buffer + NDArray buf (dim_vector (nnz, 1)); + + for (int i = 0; i < nnz; i++) + buf (i) = m.data (i); + + write_mat5_array (os, buf, save_as_floats); + } + } else if (cname == "int8") { int8NDArray m = tc.int8_array_value (); - write_mat5_integer_data (os, m, -1); + write_mat5_integer_data (os, m.fortran_vec (), -1, m.nelem ()); } else if (cname == "int16") { int16NDArray m = tc.int16_array_value (); - write_mat5_integer_data (os, m, -2); + write_mat5_integer_data (os, m.fortran_vec (), -2, m.nelem ()); } else if (cname == "int32") { int32NDArray m = tc.int32_array_value (); - write_mat5_integer_data (os, m, -4); + write_mat5_integer_data (os, m.fortran_vec (), -4, m.nelem ()); } else if (cname == "int64") { int64NDArray m = tc.int64_array_value (); - write_mat5_integer_data (os, m, -8); + write_mat5_integer_data (os, m.fortran_vec (), -8, m.nelem ()); } else if (cname == "uint8") { uint8NDArray m = tc.uint8_array_value (); - write_mat5_integer_data (os, m, 1); + write_mat5_integer_data (os, m.fortran_vec (), 1, m.nelem ()); } else if (cname == "uint16") { uint16NDArray m = tc.uint16_array_value (); - write_mat5_integer_data (os, m, 2); + write_mat5_integer_data (os, m.fortran_vec (), 2, m.nelem ()); } else if (cname == "uint32") { uint32NDArray m = tc.uint32_array_value (); - write_mat5_integer_data (os, m, 4); + write_mat5_integer_data (os, m.fortran_vec (), 4, m.nelem ()); } else if (cname == "uint64") { uint64NDArray m = tc.uint64_array_value (); - write_mat5_integer_data (os, m, 8); + write_mat5_integer_data (os, m.fortran_vec (), 8, m.nelem ()); } else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()) { diff --git a/src/oct.h b/src/oct.h --- a/src/oct.h +++ b/src/oct.h @@ -28,18 +28,18 @@ // config.h needs to be first because it includes #defines that can */ // affect other header files. -#include +#include "config.h" -#include +#include "Matrix.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "defun-dld.h" +#include "error.h" +#include "gripes.h" +#include "help.h" +#include "oct-obj.h" +#include "pager.h" +#include "utils.h" +#include "variables.h" #endif diff --git a/src/ov-base-sparse.cc b/src/ov-base-sparse.cc new file mode 100644 --- /dev/null +++ b/src/ov-base-sparse.cc @@ -0,0 +1,327 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "oct-obj.h" +#include "ov-base.h" +#include "quit.h" +#include "pr-output.h" + +#include "byte-swap.h" +#include "ls-oct-ascii.h" +#include "ls-utils.h" +#if defined (HAVE_HDF5) +#include "ls-hdf5.h" +#endif + +#include "boolSparse.h" +#include "ov-base-sparse.h" + +template +octave_value +octave_base_sparse::do_index_op (const octave_value_list& idx, + int resize_ok) +{ + octave_value retval; + + int n_idx = idx.length (); + + int nd = matrix.ndims (); + + switch (n_idx) + { + case 0: + error ("invalid number of indices (= 0) for %d-dimensional array", nd); + break; + + case 1: + { + idx_vector i = idx (0).index_vector (); + + if (! error_state) + retval = octave_value (matrix.index (i, resize_ok)); + } + break; + + default: + { + if (n_idx == 2 && nd == 2) + { + idx_vector i = idx (0).index_vector (); + + if (! error_state) + { + idx_vector j = idx (1).index_vector (); + + if (! error_state) + retval = octave_value (matrix.index (i, j, resize_ok)); + } + } + else + { + Array idx_vec (n_idx); + + for (int i = 0; i < n_idx; i++) + { + idx_vec(i) = idx(i).index_vector (); + + if (error_state) + break; + } + + if (! error_state) + retval = octave_value (matrix.index (idx_vec, resize_ok)); + } + } + break; + } + + return retval; +} + +template +octave_value +octave_base_sparse::subsref (const std::string& type, + const std::list& idx) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + retval = do_index_op (idx.front ()); + break; + + case '{': + case '.': + { + std::string nm = type_name (); + error ("%s cannot be indexed with %c", nm.c_str (), type[0]); + } + break; + + default: + panic_impossible (); + } + + return retval.next_subsref (type, idx); +} + +template +octave_value +octave_base_sparse::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + { + if (type.length () == 1) + retval = numeric_assign (type, idx, rhs); + else + { + std::string nm = type_name (); + error ("in indexed assignment of %s, last lhs index must be ()", + nm.c_str ()); + } + } + break; + + case '{': + case '.': + { + if (is_empty ()) + { + octave_value tmp = octave_value::empty_conv (type, rhs); + + retval = tmp.subsasgn (type, idx, rhs); + } + else + { + std::string nm = type_name (); + error ("%s cannot be indexed with %c", nm.c_str (), type[0]); + } + } + break; + + default: + panic_impossible (); + } + + return retval; +} + +template +void +octave_base_sparse::assign (const octave_value_list& idx, const T& rhs) +{ + int len = idx.length (); + + for (int i = 0; i < len; i++) + matrix.set_index (idx(i).index_vector ()); + + ::assign (matrix, rhs); +} + + +template +bool +octave_base_sparse::is_true (void) const +{ + bool retval = false; + dim_vector dv = matrix.dims (); + int nel = dv.numel (); + int nz = nnz (); + + if (nz == nel && nel > 0) + { + T t1 (matrix.reshape (dim_vector (nel, 1))); + + SparseBoolMatrix t2 = t1.all (); + + retval = t2(0); + } + + return retval; +} + +template +bool +octave_base_sparse::print_as_scalar (void) const +{ + dim_vector dv = dims (); + + return (dv.all_ones () || dv.any_zero ()); +} + +template +void +octave_base_sparse::print (std::ostream& os, bool pr_as_read_syntax) const +{ + print_raw (os, pr_as_read_syntax); + newline (os); +} + +template +void +octave_base_sparse::print_info (std::ostream& os, + const std::string& prefix) const +{ + matrix.print_info (os, prefix); +} + +template +void +octave_base_sparse::print_raw (std::ostream& os, + bool pr_as_read_syntax) const +{ + int nr = matrix.rows (); + int nc = matrix.cols (); + int nz = nonzero (); + + os << "Compressed Column Sparse (rows=" << nr << + ", cols=" << nc << + ", nnz=" << nz << ")"; + + // add one to the printed indices to go from + // zero-based to one-based arrays + + if (nz != 0) + { + for (int j = 0; j < nc; j++) + { + OCTAVE_QUIT; + for (int i = matrix.cidx(j); i < matrix.cidx(j+1); i++) + { + os << "\n"; + os << " (" << matrix.ridx(i)+1 << + " , " << j+1 << ") -> "; + octave_print_internal( os, matrix.data(i), pr_as_read_syntax); + } + } + } +} + +template +bool +octave_base_sparse::save_ascii (std::ostream& os, bool&, bool) +{ + dim_vector dv = this->dims (); + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + os << "# nnz: " << nnz () << "\n"; + os << "# rows: " << dv (0) << "\n"; + os << "# columns: " << dv (1) << "\n"; + + os << this->matrix; + + return true; +} + +template +bool +octave_base_sparse::load_ascii (std::istream& is) +{ + int nz = 0; + int nr = 0; + int nc = 0; + bool success = true; + + if (extract_keyword (is, "nnz", nz, true) && + extract_keyword (is, "rows", nr, true) && + extract_keyword (is, "columns", nc, true)) + { + T tmp (nr, nc, nz); + + is >> tmp; + + if (!is) + { + error ("load: failed to load matrix constant"); + success = false; + } + + matrix = tmp; + } + else + { + error ("load: failed to extract number of rows and columns"); + success = false; + } + + return success; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-base-sparse.h b/src/ov-base-sparse.h new file mode 100644 --- /dev/null +++ b/src/ov-base-sparse.h @@ -0,0 +1,157 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_base_sparse_h) +#define octave_base_sparse_h 1 + +#include + +#include +#include + +#include "str-vec.h" + +#include "error.h" +#include "oct-obj.h" +#include "ov-base.h" +#include "ov-typeinfo.h" + +#include "boolSparse.h" +#include "SparseType.h" + +class Octave_map; + +class tree_walker; + +class octave_sparse_bool_matrix; + +template +class +octave_base_sparse : public octave_base_value +{ + public: + + octave_base_sparse (void) : octave_base_value (), typ (SparseType ()) { } + + octave_base_sparse (const T& a) : octave_base_value (), matrix (a), + typ (SparseType ()) + { + if (matrix.ndims () == 0) + matrix.resize (dim_vector (0, 0)); + } + + octave_base_sparse (const T& a, const SparseType& t) : octave_base_value (), + matrix (a), typ (t) + { + if (matrix.ndims () == 0) + matrix.resize (dim_vector (0, 0)); + } + + octave_base_sparse (const octave_base_sparse& a) : + octave_base_value (), matrix (a.matrix), typ (a.typ) { } + + ~octave_base_sparse (void) { } + + octave_value *clone (void) const { return new octave_base_sparse (*this); } + octave_value *empty_clone (void) const + { return new octave_base_sparse (); } + + int nnz (void) const { return matrix.nnz (); } + int nonzero (void) const { return matrix.nonzero (); } + + size_t byte_size (void) const { return matrix.byte_size (); } + + octave_value squeeze (void) const { return matrix.squeeze (); } + + octave_value subsref (const std::string& type, + const std::list& idx); + + octave_value_list subsref (const std::string&, + const std::list&, int) + { + panic_impossible (); + return octave_value_list (); + } + + octave_value subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + + void assign (const octave_value_list& idx, const T& rhs); + + dim_vector dims (void) const { return matrix.dims (); } + + octave_value do_index_op (const octave_value_list& idx, int resize_ok); + + octave_value do_index_op (const octave_value_list& idx) + { return do_index_op (idx, 0); } + + octave_value reshape (const dim_vector& new_dims) const + { return T (matrix.reshape (new_dims)); } + + octave_value permute (const Array& vec, bool inv = false) const + { return T (matrix.permute (vec, inv)); } + + octave_value resize (const dim_vector& dv) const + { T retval (matrix); retval.resize (dv); return retval; } + + octave_value all (int dim = 0) const { return matrix.all (dim); } + octave_value any (int dim = 0) const { return matrix.any (dim); } + + bool is_matrix_type (void) const { return true; } + + bool is_numeric_type (void) const { return true; } + + bool is_defined (void) const { return true; } + + bool is_constant (void) const { return true; } + + bool is_true (void) const; + + int capacity (void) const { return matrix.capacity (); } + + bool print_as_scalar (void) const; + + void print (std::ostream& os, bool pr_as_read_syntax = false) const; + + void print_info (std::ostream& os, const std::string& prefix) const; + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + +protected: + + T matrix; + + SparseType typ; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-base.cc b/src/ov-base.cc --- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -413,6 +413,30 @@ return retval; } +SparseMatrix +octave_base_value::sparse_matrix_value (bool) const +{ + SparseMatrix retval; + gripe_wrong_type_arg ("octave_base_value::sparse_matrix_value()", type_name ()); + return retval; +} + +SparseComplexMatrix +octave_base_value::sparse_complex_matrix_value (bool) const +{ + SparseComplexMatrix retval; + gripe_wrong_type_arg ("octave_base_value::sparse_complex_matrix_value()", type_name ()); + return retval; +} + +SparseBoolMatrix +octave_base_value::sparse_bool_matrix_value (bool) const +{ + SparseBoolMatrix retval; + gripe_wrong_type_arg ("octave_base_value::sparse_bool_matrix_value()", type_name ()); + return retval; +} + octave_int8 octave_base_value::int8_scalar_value (void) const { diff --git a/src/ov-base.h b/src/ov-base.h --- a/src/ov-base.h +++ b/src/ov-base.h @@ -94,6 +94,8 @@ int numel (void) const { return dims ().numel (); } + int capacity (void) const { return numel (); } + size_t byte_size (void) const { return 0; } octave_value reshape (const dim_vector&) const; @@ -218,6 +220,12 @@ charNDArray char_array_value (bool = false) const; + SparseMatrix sparse_matrix_value (bool = false) const; + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const; + + SparseBoolMatrix sparse_bool_matrix_value (bool = false) const; + octave_int8 int8_scalar_value (void) const; octave_int16 int16_scalar_value (void) const; diff --git a/src/ov-bool-mat.h b/src/ov-bool-mat.h --- a/src/ov-bool-mat.h +++ b/src/ov-bool-mat.h @@ -108,6 +108,15 @@ boolNDArray bool_array_value (void) const { return matrix; } + SparseMatrix sparse_matrix_value (bool = false) const + { return SparseMatrix (Matrix (matrix.matrix_value ())); } + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const + { return SparseComplexMatrix (ComplexMatrix (matrix.matrix_value ())); } + + SparseBoolMatrix sparse_bool_matrix_value (bool = false) const + { return SparseBoolMatrix (matrix.matrix_value ()); } + octave_value convert_to_str_internal (bool pad, bool force) const; void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff --git a/src/ov-bool-sparse.cc b/src/ov-bool-sparse.cc new file mode 100644 --- /dev/null +++ b/src/ov-bool-sparse.cc @@ -0,0 +1,696 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "ov-base.h" +#include "ov-scalar.h" +#include "ov-bool.h" +#include "ov-bool-mat.h" +#include "gripes.h" +#include "ops.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" +#include "ov-bool-sparse.h" + +#include "ov-base-sparse.h" +#include "ov-base-sparse.cc" + +template class octave_base_sparse; + +DEFINE_OCTAVE_ALLOCATOR (octave_sparse_bool_matrix); + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_bool_matrix, "sparse bool matrix", "sparse"); + +static octave_value * +default_numeric_conversion_function (const octave_value& a) +{ + CAST_CONV_ARG (const octave_sparse_bool_matrix&); + + return new octave_sparse_matrix (SparseMatrix (v.sparse_bool_matrix_value ())); +} + +type_conv_fcn +octave_sparse_bool_matrix::numeric_conversion_function (void) const +{ + return default_numeric_conversion_function; +} + +octave_value * +octave_sparse_bool_matrix::try_narrowing_conversion (void) +{ + octave_value *retval = 0; + + // Don't use numel, since it can overflow for very large matrices + // Note that for the second test, this means it becomes approximative + // since it involves a cast to double to avoid issues of overflow + if (matrix.rows () == 1 && matrix.cols () == 1) + { + // Const copy of the matrix, so the right version of () operator used + const SparseBoolMatrix tmp (matrix); + + retval = new octave_bool (tmp (0)); + } + else if (matrix.cols () > 0 && matrix.rows () > 0 && + double (matrix.byte_size ()) > double (matrix.rows ()) * + double (matrix.cols ()) * sizeof (bool)) + retval = new octave_bool_matrix (matrix.matrix_value ()); + + return retval; +} + +bool +octave_sparse_bool_matrix::valid_as_scalar_index (void) const +{ + // XXX FIXME XXX + return false; +} + +double +octave_sparse_bool_matrix::double_value (bool) const +{ + double retval = lo_ieee_nan_value (); + + if (numel () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("bool sparse matrix", "real scalar"); + + retval = matrix (0, 0); + } + else + gripe_invalid_conversion ("bool sparse matrix", "real scalar"); + + return retval; +} + +Complex +octave_sparse_bool_matrix::complex_value (bool) const +{ + double tmp = lo_ieee_nan_value (); + + Complex retval (tmp, tmp); + + // XXX FIXME XXX -- maybe this should be a function, valid_as_scalar() + if (rows () > 0 && columns () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("bool sparse matrix", "complex scalar"); + + retval = matrix (0, 0); + } + else + gripe_invalid_conversion ("bool sparse matrix", "complex scalar"); + + return retval; +} + +octave_value +octave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force) const +{ + octave_value tmp = octave_value (array_value ()); + return tmp.convert_to_str (pad, force); +} + +// XXX FIXME XXX These are inefficient ways of creating full matrices + +Matrix +octave_sparse_bool_matrix::matrix_value (bool) const +{ + return Matrix (matrix.matrix_value ()); +} + +ComplexMatrix +octave_sparse_bool_matrix::complex_matrix_value (bool) const +{ + return ComplexMatrix (matrix.matrix_value ()); +} + +ComplexNDArray +octave_sparse_bool_matrix::complex_array_value (bool) const +{ + return ComplexNDArray (ComplexMatrix (matrix.matrix_value ())); +} + +NDArray +octave_sparse_bool_matrix::array_value (bool) const +{ + return NDArray (Matrix(matrix.matrix_value ())); +} + +boolMatrix +octave_sparse_bool_matrix::bool_matrix_value (void) const +{ + return matrix.matrix_value (); +} + +boolNDArray +octave_sparse_bool_matrix::bool_array_value (void) const +{ + return boolNDArray (matrix.matrix_value ()); +} + + +SparseMatrix +octave_sparse_bool_matrix::sparse_matrix_value (void) const +{ + return SparseMatrix (this->matrix); +} + +SparseComplexMatrix +octave_sparse_bool_matrix::sparse_complex_matrix_value (void) const +{ + return SparseComplexMatrix (this->matrix); +} + +bool +octave_sparse_bool_matrix::save_binary (std::ostream& os, bool&) +{ + dim_vector d = this->dims (); + if (d.length() < 1) + return false; + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + int nr = d(0); + int nc = d(1); + int nz = nnz (); + + FOUR_BYTE_INT itmp; + // Use negative value for ndims to be consistent with other formats + itmp= -2; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nr; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nc; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nz; + os.write (X_CAST (char *, &itmp), 4); + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + itmp = matrix.cidx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + itmp = matrix.ridx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + OCTAVE_LOCAL_BUFFER (char, htmp, nz); + + for (int i = 0; i < nz; i++) + htmp[i] = (matrix.data (i) ? 1 : 0); + + os.write (htmp, nz); + + return true; +} + +bool +octave_sparse_bool_matrix::load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt) +{ + FOUR_BYTE_INT nz, nc, nr, tmp; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + + if (swap) + swap_bytes<4> (&tmp); + + if (tmp != -2) { + error("load: only 2D sparse matrices are supported"); + return false; + } + + if (! is.read (X_CAST (char *, &nr), 4)) + return false; + if (! is.read (X_CAST (char *, &nc), 4)) + return false; + if (! is.read (X_CAST (char *, &nz), 4)) + return false; + + if (swap) + { + swap_bytes<4> (&nr); + swap_bytes<4> (&nc); + swap_bytes<4> (&nz); + } + + SparseBoolMatrix m (nr, nc, nz); + + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.cidx(i) = tmp; + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.ridx(i) = tmp; + } + + if (error_state || ! is) + return false; + + OCTAVE_LOCAL_BUFFER (char, htmp, nz); + + if (! is.read (htmp, nz)) + return false; + + for (int i = 0; i < nz; i++) + m.data(i) = (htmp[i] ? 1 : 0); + + matrix = m; + + return true; +} + +#if defined (HAVE_HDF5) +bool +octave_sparse_bool_matrix::save_hdf5 (hid_t loc_id, const char *name, bool) +{ + dim_vector dv = dims (); + int empty = save_hdf5_empty (loc_id, name, dv); + if (empty) + return (empty > 0); + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + hid_t group_hid = H5Gcreate (loc_id, name, 0); + if (group_hid < 0) + return false; + + hid_t space_hid = -1, data_hid = -1; + bool retval = true; + SparseBoolMatrix m = sparse_bool_matrix_value (); + int tmp; + hsize_t hdims[2]; + + space_hid = H5Screate_simple (0, hdims, (hsize_t*) 0); + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.rows (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.cols (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.nnz (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.cols() + 1; + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + int * itmp = m.xcidx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.nnz(); + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "data", H5T_NATIVE_HBOOL, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + hbool_t htmp[m.nnz ()]; + for (int i = 0; i < m.nnz (); i++) + htmp[i] = m.xdata(i); + + retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void*) htmp) >= 0; + H5Dclose (data_hid); + H5Sclose (space_hid); + H5Gclose (group_hid); + + return retval; +} + +bool +octave_sparse_bool_matrix::load_hdf5 (hid_t loc_id, const char *name, + bool /* have_h5giterate_bug */) +{ + int nr, nc, nz; + hid_t group_hid, data_hid, space_hid; + hsize_t rank; + + dim_vector dv; + int empty = load_hdf5_empty (loc_id, name, dv); + if (empty > 0) + matrix.resize(dv); + if (empty) + return (empty > 0); + + group_hid = H5Gopen (loc_id, name); + if (group_hid < 0 ) return false; + + data_hid = H5Dopen (group_hid, "nr"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nr) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nc"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nc) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nz"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nz) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + SparseBoolMatrix m (nr, nc, nz); + + data_hid = H5Dopen (group_hid, "cidx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); + OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nc + 1 || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + int *itmp = m.xcidx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "ridx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "data"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + hbool_t htmp[nz]; + bool retval = false; + if (H5Dread (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) htmp) >= 0) + { + retval = true; + + for (int i = 0; i < nz; i++) + m.xdata(i) = htmp[i]; + + matrix = m; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + + return retval; +} +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-bool-sparse.h b/src/ov-bool-sparse.h new file mode 100644 --- /dev/null +++ b/src/ov-bool-sparse.h @@ -0,0 +1,149 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_bool_matrix_h) +#define octave_sparse_bool_matrix_h 1 + +#include + +#include +#include + +#include "mx-base.h" +#include "oct-alloc.h" +#include "so-array.h" +#include "str-vec.h" + +#include "error.h" +#include "oct-stream.h" +#include "ov-base.h" +#include "ov-typeinfo.h" + +#include "boolSparse.h" +#include "ov-base-sparse.h" +#include "ov-re-sparse.h" + +class Octave_map; +class octave_value_list; + +class tree_walker; + +class +octave_sparse_bool_matrix : public octave_base_sparse +{ +public: + + octave_sparse_bool_matrix (void) + : octave_base_sparse () { } + + octave_sparse_bool_matrix (const SparseBoolMatrix& bnda) + : octave_base_sparse (bnda) { } + + octave_sparse_bool_matrix (const SparseBoolMatrix& bnda, + const SparseType& t) + : octave_base_sparse (bnda, t) { } + + octave_sparse_bool_matrix (const boolNDArray& m) + : octave_base_sparse (SparseBoolMatrix (m)) { } + + octave_sparse_bool_matrix (const boolMatrix& m) + : octave_base_sparse (SparseBoolMatrix (m)) { } + + octave_sparse_bool_matrix (const Sparse& a) + : octave_base_sparse (a) { } + + octave_sparse_bool_matrix (const octave_sparse_bool_matrix& bm) + : octave_base_sparse (bm) { } + + ~octave_sparse_bool_matrix (void) { } + + octave_value *clone (void) const { return new octave_sparse_bool_matrix (*this); } + octave_value *empty_clone (void) const { return new octave_sparse_bool_matrix (); } + + type_conv_fcn numeric_conversion_function (void) const; + + octave_value *try_narrowing_conversion (void); + +#if 0 + idx_vector index_vector (void) const { return idx_vector (matrix); } +#endif + + bool is_bool_matrix (void) const { return true; } + + bool is_bool_type (void) const { return true; } + + bool is_real_type (void) const { return true; } + + bool valid_as_scalar_index (void) const; + + double double_value (bool = false) const; + + double scalar_value (bool frc_str_conv = false) const + { return double_value (frc_str_conv); } + + Matrix matrix_value (bool = false) const; + + NDArray array_value (bool = false) const; + + Complex complex_value (bool = false) const; + + ComplexMatrix complex_matrix_value (bool = false) const; + + ComplexNDArray complex_array_value (bool = false) const; + + boolMatrix bool_matrix_value (void) const; + + boolNDArray bool_array_value (void) const; + + SparseMatrix sparse_matrix_value (void) const; + + SparseComplexMatrix sparse_complex_matrix_value (void) const; + + SparseBoolMatrix sparse_bool_matrix_value (void) const + { return matrix; } + + octave_value convert_to_str_internal (bool pad, bool force) const; + + bool save_binary (std::ostream& os, bool& save_as_floats); + + bool load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt); + +#if defined (HAVE_HDF5) + bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats); + + bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug); +#endif + +protected: + + DECLARE_OCTAVE_ALLOCATOR + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-cell.cc b/src/ov-cell.cc --- a/src/ov-cell.cc +++ b/src/ov-cell.cc @@ -25,6 +25,7 @@ #endif #include +#include #include "lo-sstream.h" #include "lo-utils.h" diff --git a/src/ov-cx-mat.cc b/src/ov-cx-mat.cc --- a/src/ov-cx-mat.cc +++ b/src/ov-cx-mat.cc @@ -179,6 +179,25 @@ return matrix.matrix_value (); } +SparseMatrix +octave_complex_matrix::sparse_matrix_value (bool force_conversion) const +{ + SparseMatrix retval; + + if (! force_conversion && Vwarn_imag_to_real) + gripe_implicit_conversion ("complex matrix", "real matrix"); + + retval = SparseMatrix (::real (matrix.matrix_value ())); + + return retval; +} + +SparseComplexMatrix +octave_complex_matrix::sparse_complex_matrix_value (bool) const +{ + return SparseComplexMatrix (matrix.matrix_value ()); +} + static ComplexMatrix strip_infnan (const ComplexMatrix& m) { diff --git a/src/ov-cx-mat.h b/src/ov-cx-mat.h --- a/src/ov-cx-mat.h +++ b/src/ov-cx-mat.h @@ -104,6 +104,10 @@ ComplexNDArray complex_array_value (bool = false) const { return matrix; } + SparseMatrix sparse_matrix_value (bool = false) const; + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const; + void increment (void) { matrix += Complex (1.0); } void decrement (void) { matrix -= Complex (1.0); } diff --git a/src/ov-cx-sparse.cc b/src/ov-cx-sparse.cc new file mode 100644 --- /dev/null +++ b/src/ov-cx-sparse.cc @@ -0,0 +1,761 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "ov-base.h" +#include "ov-scalar.h" +#include "ov-complex.h" +#include "gripes.h" + +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" + +#include "ov-base-sparse.h" +#include "ov-base-sparse.cc" + +#include "ov-bool-sparse.h" + +template class octave_base_sparse; + +DEFINE_OCTAVE_ALLOCATOR (octave_sparse_complex_matrix); + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_complex_matrix, "sparse complex matrix", "sparse"); + +octave_value * +octave_sparse_complex_matrix::try_narrowing_conversion (void) +{ + octave_value *retval = 0; + + int nr = matrix.rows (); + int nc = matrix.cols (); + + // Don't use numel, since it can overflow for very large matrices + // Note that for the tests on matrix size, they become approximative + // since they involves a cast to double to avoid issues of overflow + if (matrix.rows () == 1 && matrix.cols () == 1) + { + // Const copy of the matrix, so the right version of () operator used + const SparseComplexMatrix tmp (matrix); + + Complex c = tmp (0, 0); + + if (imag (c) == 0.0) + retval = new octave_scalar (std::real (c)); + else + retval = new octave_complex (c); + } + else if (nr == 0 || nc == 0) + retval = new octave_matrix (Matrix (nr, nc)); + else if (matrix.all_elements_are_real ()) + if (matrix.cols () > 0 && matrix.rows () > 0 && + double (matrix.byte_size ()) > double (matrix.rows ()) * + double (matrix.cols ()) * sizeof (double)) + retval = new octave_matrix (::real (matrix.matrix_value ())); + else + retval = new octave_sparse_matrix (::real (matrix)); + else if (matrix.cols () > 0 && matrix.rows () > 0 && + double (matrix.byte_size ()) > double (matrix.rows ()) * + double (matrix.cols ()) * sizeof (Complex)) + retval = new octave_complex_matrix (matrix.matrix_value ()); + + return retval; +} + +void +octave_sparse_complex_matrix::assign (const octave_value_list& idx, + const SparseComplexMatrix& rhs) +{ + octave_base_sparse::assign (idx, rhs); +} + +void +octave_sparse_complex_matrix::assign (const octave_value_list& idx, + const SparseMatrix& rhs) +{ + int len = idx.length (); + + for (int i = 0; i < len; i++) + matrix.set_index (idx(i).index_vector ()); + + ::assign (matrix, rhs); +} + +bool +octave_sparse_complex_matrix::valid_as_scalar_index (void) const +{ + // XXX FIXME XXX + return false; +} + +double +octave_sparse_complex_matrix::double_value (bool force_conversion) const +{ + double retval = lo_ieee_nan_value (); + + if (! force_conversion && Vwarn_imag_to_real) + gripe_implicit_conversion ("complex sparse matrix", "real scalar"); + + // XXX FIXME XXX -- maybe this should be a function, valid_as_scalar() + if (numel () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("complex sparse matrix", "real scalar"); + + retval = std::real (matrix (0, 0)); + } + else + gripe_invalid_conversion ("complex sparse matrix", "real scalar"); + + return retval; +} + +Matrix +octave_sparse_complex_matrix::matrix_value (bool force_conversion) const +{ + Matrix retval; + + if (! force_conversion && Vwarn_imag_to_real) + gripe_implicit_conversion ("complex sparse matrix", "real matrix"); + + retval = ::real (matrix.matrix_value ()); + + return retval; +} + +Complex +octave_sparse_complex_matrix::complex_value (bool) const +{ + double tmp = lo_ieee_nan_value (); + + Complex retval (tmp, tmp); + + // XXX FIXME XXX -- maybe this should be a function, valid_as_scalar() + if (numel () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("complex sparse matrix", "real scalar"); + + retval = matrix (0, 0); + } + else + gripe_invalid_conversion ("complex sparse matrix", "real scalar"); + + return retval; +} + +ComplexMatrix +octave_sparse_complex_matrix::complex_matrix_value (bool) const +{ + return matrix.matrix_value (); +} + +ComplexNDArray +octave_sparse_complex_matrix::complex_array_value (bool) const +{ + return ComplexNDArray (matrix.matrix_value ()); +} + +SparseMatrix +octave_sparse_complex_matrix::sparse_matrix_value (bool force_conversion) const +{ + SparseMatrix retval; + + if (! force_conversion && Vwarn_imag_to_real) + gripe_implicit_conversion ("complex sparse matrix", + "real sparse matrix"); + + retval = ::real (matrix); + + return retval; +} + +bool +octave_sparse_complex_matrix::save_binary (std::ostream& os, + bool&save_as_floats) +{ + dim_vector d = this->dims (); + if (d.length() < 1) + return false; + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + int nr = d(0); + int nc = d(1); + int nz = nnz (); + + FOUR_BYTE_INT itmp; + // Use negative value for ndims to be consistent with other formats + itmp= -2; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nr; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nc; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nz; + os.write (X_CAST (char *, &itmp), 4); + + save_type st = LS_DOUBLE; + if (save_as_floats) + { + if (matrix.too_large_for_float ()) + { + warning ("save: some values too large to save as floats --"); + warning ("save: saving as doubles instead"); + } + else + st = LS_FLOAT; + } + else if (matrix.nnz () > 8192) // XXX FIXME XXX -- make this configurable. + { + double max_val, min_val; + if (matrix.all_integers (max_val, min_val)) + st = get_save_type (max_val, min_val); + } + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + itmp = matrix.cidx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + itmp = matrix.ridx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + write_doubles (os, X_CAST (const double *, matrix.data()), st, 2 * nz); + + return true; +} + +bool +octave_sparse_complex_matrix::load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt) +{ + FOUR_BYTE_INT nz, nc, nr, tmp; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + + if (swap) + swap_bytes<4> (&tmp); + + if (tmp != -2) { + error("load: only 2D sparse matrices are supported"); + return false; + } + + if (! is.read (X_CAST (char *, &nr), 4)) + return false; + if (! is.read (X_CAST (char *, &nc), 4)) + return false; + if (! is.read (X_CAST (char *, &nz), 4)) + return false; + + if (swap) + { + swap_bytes<4> (&nr); + swap_bytes<4> (&nc); + swap_bytes<4> (&nz); + } + + SparseComplexMatrix m (nr, nc, nz); + + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.cidx(i) = tmp; + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.ridx(i) = tmp; + } + + if (! is.read (X_CAST (char *, &tmp), 1)) + return false; + + read_doubles (is, X_CAST(double *, m.data()), X_CAST (save_type, tmp), + 2 * nz, swap, fmt); + + if (error_state || ! is) + return false; + matrix = m; + + return true; +} + +#if defined (HAVE_HDF5) +bool +octave_sparse_complex_matrix::save_hdf5 (hid_t loc_id, const char *name, + bool save_as_floats) +{ + dim_vector dv = dims (); + int empty = save_hdf5_empty (loc_id, name, dv); + if (empty) + return (empty > 0); + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + hid_t group_hid = H5Gcreate (loc_id, name, 0); + if (group_hid < 0) + return false; + + hid_t space_hid = -1, data_hid = -1; + bool retval = true; + SparseComplexMatrix m = sparse_complex_matrix_value (); + int tmp; + hsize_t hdims[2]; + + space_hid = H5Screate_simple (0, hdims, (hsize_t*) 0); + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.rows (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.cols (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.nnz (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.cols() + 1; + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + int * itmp = m.xcidx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.nnz(); + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + hid_t save_type_hid = H5T_NATIVE_DOUBLE; + + if (save_as_floats) + { + if (m.too_large_for_float ()) + { + warning ("save: some values too large to save as floats --"); + warning ("save: saving as doubles instead"); + } + else + save_type_hid = H5T_NATIVE_FLOAT; + } +#if HAVE_HDF5_INT2FLOAT_CONVERSIONS + // hdf5 currently doesn't support float/integer conversions + else + { + double max_val, min_val; + + if (m.all_integers (max_val, min_val)) + save_type_hid + = save_type_to_hdf5 (get_save_type (max_val, min_val)); + } +#endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */ + + hid_t type_hid = hdf5_make_complex_type (save_type_hid); + if (type_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "data", type_hid, space_hid, H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + hid_t complex_type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE); + retval = false; + if (complex_type_hid >= 0) + { + Complex * ctmp = m.xdata (); + + retval = H5Dwrite (data_hid, complex_type_hid, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void*) ctmp) >= 0; + } + + H5Dclose (data_hid); + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + + return retval; +} + +bool +octave_sparse_complex_matrix::load_hdf5 (hid_t loc_id, const char *name, + bool /* have_h5giterate_bug */) +{ + int nr, nc, nz; + hid_t group_hid, data_hid, space_hid; + hsize_t rank; + + dim_vector dv; + int empty = load_hdf5_empty (loc_id, name, dv); + if (empty > 0) + matrix.resize(dv); + if (empty) + return (empty > 0); + + group_hid = H5Gopen (loc_id, name); + if (group_hid < 0 ) return false; + + data_hid = H5Dopen (group_hid, "nr"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nr) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nc"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nc) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nz"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nz) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + SparseComplexMatrix m (nr, nc, nz); + + data_hid = H5Dopen (group_hid, "cidx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); + OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nc + 1 || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + int *itmp = m.xcidx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "ridx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "data"); + hid_t type_hid = H5Dget_type (data_hid); + + hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE); + + if (! hdf5_types_compatible (type_hid, complex_type)) + { + H5Tclose (complex_type); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + Complex *ctmp = m.xdata (); + bool retval = false; + if (H5Dread (data_hid, complex_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void *) ctmp) >= 0) + { + retval = true; + matrix = m; + } + + H5Tclose (complex_type); + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + + return retval; +} + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-cx-sparse.h b/src/ov-cx-sparse.h new file mode 100644 --- /dev/null +++ b/src/ov-cx-sparse.h @@ -0,0 +1,147 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_complex_matrix_h) +#define octave_sparse_complex_matrix_h 1 + +#include + +#include +#include + +#include "mx-base.h" +#include "oct-alloc.h" +#include "so-array.h" +#include "str-vec.h" + +#include "error.h" +#include "oct-stream.h" +#include "ov-base.h" +#include "ov-typeinfo.h" + +#include "CSparse.h" +#include "ov-base-sparse.h" +#include "ov-re-sparse.h" +#include "ov-bool-sparse.h" + +class Octave_map; +class octave_value_list; + +class tree_walker; + +class +octave_sparse_complex_matrix : public octave_base_sparse +{ +public: + + octave_sparse_complex_matrix (void) + : octave_base_sparse () { } + + octave_sparse_complex_matrix (const ComplexNDArray& m) + : octave_base_sparse (SparseComplexMatrix (m)) { } + + octave_sparse_complex_matrix (const ComplexMatrix& m) + : octave_base_sparse (SparseComplexMatrix (m)) { } + + octave_sparse_complex_matrix (const SparseComplexMatrix& m) + : octave_base_sparse (m) { } + + octave_sparse_complex_matrix (const SparseComplexMatrix& m, + const SparseType &t) + : octave_base_sparse (m, t) { } + + octave_sparse_complex_matrix (const MSparse& m) + : octave_base_sparse (m) { } + + octave_sparse_complex_matrix (const octave_sparse_complex_matrix& cm) + : octave_base_sparse (cm) { } + + ~octave_sparse_complex_matrix (void) { } + + octave_value *clone (void) const { return new octave_sparse_complex_matrix (*this); } + octave_value *empty_clone (void) const { return new octave_sparse_complex_matrix (); } + + octave_value *try_narrowing_conversion (void); + + void assign (const octave_value_list& idx, const SparseComplexMatrix& rhs); + + void assign (const octave_value_list& idx, const SparseMatrix& rhs); + + bool is_complex_matrix (void) const { return true; } + + bool is_complex_type (void) const { return true; } + + bool valid_as_scalar_index (void) const; + + double double_value (bool = false) const; + + double scalar_value (bool frc_str_conv = false) const + { return double_value (frc_str_conv); } + + Matrix matrix_value (bool = false) const; + + Complex complex_value (bool = false) const; + + ComplexMatrix complex_matrix_value (bool = false) const; + + ComplexNDArray complex_array_value (bool = false) const; + + SparseMatrix sparse_matrix_value (bool = false) const; + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const + { return matrix; } + +#if 0 + int write (octave_stream& os, int block_size, + oct_data_conv::data_type output_type, int skip, + oct_mach_info::float_format flt_fmt) const + { + // Yes, for compatibility, we drop the imaginary part here. + return os.write (matrix_value (true), block_size, output_type, + skip, flt_fmt); + } +#endif + + bool save_binary (std::ostream& os, bool& save_as_floats); + + bool load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt); + +#if defined (HAVE_HDF5) + bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats); + + bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug); +#endif + +private: + + DECLARE_OCTAVE_ALLOCATOR + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-fcn-handle.cc b/src/ov-fcn-handle.cc --- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -25,6 +25,7 @@ #endif #include +#include #include "defun.h" #include "error.h" diff --git a/src/ov-fcn-inline.cc b/src/ov-fcn-inline.cc --- a/src/ov-fcn-inline.cc +++ b/src/ov-fcn-inline.cc @@ -29,6 +29,7 @@ #include #include +#include #include "defun.h" #include "error.h" diff --git a/src/ov-fcn-inline.h b/src/ov-fcn-inline.h --- a/src/ov-fcn-inline.h +++ b/src/ov-fcn-inline.h @@ -17,10 +17,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -In addition to the terms of the GPL, you are permitted to link -this program with any Open Source program, as defined by the -Open Source Initiative (www.opensource.org) - */ #if !defined (octave_fcn_inline_h) diff --git a/src/ov-int16.cc b/src/ov-int16.cc --- a/src/ov-int16.cc +++ b/src/ov-int16.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-int32.cc b/src/ov-int32.cc --- a/src/ov-int32.cc +++ b/src/ov-int32.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-int64.cc b/src/ov-int64.cc --- a/src/ov-int64.cc +++ b/src/ov-int64.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-int8.cc b/src/ov-int8.cc --- a/src/ov-int8.cc +++ b/src/ov-int8.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-re-mat.cc b/src/ov-re-mat.cc --- a/src/ov-re-mat.cc +++ b/src/ov-re-mat.cc @@ -160,6 +160,21 @@ return retval; } +SparseMatrix +octave_matrix::sparse_matrix_value (bool) const +{ + return SparseMatrix (matrix.matrix_value ()); +} + +SparseComplexMatrix +octave_matrix::sparse_complex_matrix_value (bool) const +{ + // XXX FIXME XXX Need a SparseComplexMatrix (Matrix) constructor to make + // this function more efficient. Then this should become + // return SparseComplexMatrix (matrix.matrix_value ()); + return SparseComplexMatrix (sparse_matrix_value ()); +} + streamoff_array octave_matrix::streamoff_array_value (void) const { diff --git a/src/ov-re-mat.h b/src/ov-re-mat.h --- a/src/ov-re-mat.h +++ b/src/ov-re-mat.h @@ -107,6 +107,10 @@ NDArray array_value (bool = false) const { return matrix; } + SparseMatrix sparse_matrix_value (bool = false) const; + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const; + streamoff_array streamoff_array_value (void) const; void increment (void) { matrix += 1.0; } diff --git a/src/ov-re-sparse.cc b/src/ov-re-sparse.cc new file mode 100644 --- /dev/null +++ b/src/ov-re-sparse.cc @@ -0,0 +1,704 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "ov-base.h" +#include "ov-scalar.h" +#include "gripes.h" + +#include "ls-hdf5.h" + +#include "ov-re-sparse.h" + +#include "ov-base-sparse.h" +#include "ov-base-sparse.cc" + +#include "ov-bool-sparse.h" + +template class octave_base_sparse; + +DEFINE_OCTAVE_ALLOCATOR (octave_sparse_matrix); + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_matrix, "sparse matrix", "sparse"); + +octave_value * +octave_sparse_matrix::try_narrowing_conversion (void) +{ + octave_value *retval = 0; + + // Don't use numel, since it can overflow for very large matrices + // Note that for the second test, this means it becomes approximative + // since it involves a cast to double to avoid issues of overflow + if (matrix.rows () == 1 && matrix.cols () == 1) + { + // Const copy of the matrix, so the right version of () operator used + const SparseMatrix tmp (matrix); + + retval = new octave_scalar (tmp (0)); + } + else if (matrix.cols () > 0 && matrix.rows () > 0 && + double (matrix.byte_size ()) > double (matrix.rows ()) * + double (matrix.cols ()) * sizeof (double)) + retval = new octave_matrix (matrix.matrix_value ()); + + return retval; +} + +bool +octave_sparse_matrix::valid_as_scalar_index (void) const +{ + // XXX FIXME XXX + return false; +} + +double +octave_sparse_matrix::double_value (bool) const +{ + double retval = lo_ieee_nan_value (); + + if (numel () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("real sparse matrix", "real scalar"); + + retval = matrix (0, 0); + } + else + gripe_invalid_conversion ("real sparse matrix", "real scalar"); + + return retval; +} + +Complex +octave_sparse_matrix::complex_value (bool) const +{ + double tmp = lo_ieee_nan_value (); + + Complex retval (tmp, tmp); + + // XXX FIXME XXX -- maybe this should be a function, valid_as_scalar() + if (rows () > 0 && columns () > 0) + { + // XXX FIXME XXX -- is warn_fortran_indexing the right variable here? + if (Vwarn_fortran_indexing) + gripe_implicit_conversion ("real sparse matrix", "complex scalar"); + + retval = matrix (0, 0); + } + else + gripe_invalid_conversion ("real sparse matrix", "complex scalar"); + + return retval; +} + +Matrix +octave_sparse_matrix::matrix_value (bool) const +{ + return matrix.matrix_value (); +} + +ComplexMatrix +octave_sparse_matrix::complex_matrix_value (bool) const +{ + return ComplexMatrix (matrix.matrix_value ()); +} + +ComplexNDArray +octave_sparse_matrix::complex_array_value (bool) const +{ + return ComplexNDArray (ComplexMatrix (matrix.matrix_value ())); +} + +NDArray +octave_sparse_matrix::array_value (bool) const +{ + return NDArray (matrix.matrix_value ()); +} + +streamoff_array +octave_sparse_matrix::streamoff_array_value (void) const +{ + streamoff_array retval (dims ()); + int nc = matrix.cols (); + int nr = matrix.rows (); + + for (int j = 0; j < nc; j++) + for (int i = matrix.cidx(i); i < matrix.cidx(i+1); i++) + { + double d = matrix.data(i); + + if (D_NINT (d) == d) + { + retval(matrix.ridx(i) + nr * j) = + std::streamoff (static_cast (d)); + } + else + { + error ("conversion to streamoff_array value failed"); + break; + } + } + + return retval; +} + +bool +octave_sparse_matrix::save_binary (std::ostream& os, bool&save_as_floats) +{ + dim_vector d = this->dims (); + if (d.length() < 1) + return false; + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + int nr = d(0); + int nc = d(1); + int nz = nnz (); + + FOUR_BYTE_INT itmp; + // Use negative value for ndims to be consistent with other formats + itmp= -2; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nr; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nc; + os.write (X_CAST (char *, &itmp), 4); + + itmp= nz; + os.write (X_CAST (char *, &itmp), 4); + + save_type st = LS_DOUBLE; + if (save_as_floats) + { + if (matrix.too_large_for_float ()) + { + warning ("save: some values too large to save as floats --"); + warning ("save: saving as doubles instead"); + } + else + st = LS_FLOAT; + } + else if (matrix.nnz () > 8192) // XXX FIXME XXX -- make this configurable. + { + double max_val, min_val; + if (matrix.all_integers (max_val, min_val)) + st = get_save_type (max_val, min_val); + } + + // add one to the printed indices to go from + // zero-based to one-based arrays + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + itmp = matrix.cidx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + itmp = matrix.ridx(i); + os.write (X_CAST (char *, &itmp), 4); + } + + write_doubles (os, matrix.data(), st, nz); + + return true; +} + +bool +octave_sparse_matrix::load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt) +{ + FOUR_BYTE_INT nz, nc, nr, tmp; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + + if (swap) + swap_bytes<4> (&tmp); + + if (tmp != -2) { + error("load: only 2D sparse matrices are supported"); + return false; + } + + if (! is.read (X_CAST (char *, &nr), 4)) + return false; + if (! is.read (X_CAST (char *, &nc), 4)) + return false; + if (! is.read (X_CAST (char *, &nz), 4)) + return false; + + if (swap) + { + swap_bytes<4> (&nr); + swap_bytes<4> (&nc); + swap_bytes<4> (&nz); + } + + SparseMatrix m (nr, nc, nz); + + for (int i = 0; i < nc+1; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.xcidx(i) = tmp; + } + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + if (! is.read (X_CAST (char *, &tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + m.xridx(i) = tmp; + } + + if (! is.read (X_CAST (char *, &tmp), 1)) + return false; + + read_doubles (is, m.xdata(), X_CAST (save_type, tmp), nz, swap, fmt); + + if (error_state || ! is) + return false; + matrix = m; + + return true; +} + +#if defined (HAVE_HDF5) +bool +octave_sparse_matrix::save_hdf5 (hid_t loc_id, const char *name, + bool save_as_floats) +{ + dim_vector dv = dims (); + int empty = save_hdf5_empty (loc_id, name, dv); + if (empty) + return (empty > 0); + + // Ensure that additional memory is deallocated + matrix.maybe_compress (); + + hid_t group_hid = H5Gcreate (loc_id, name, 0); + if (group_hid < 0) + return false; + + hid_t space_hid = -1, data_hid = -1; + bool retval = true; + SparseMatrix m = sparse_matrix_value (); + int tmp; + hsize_t hdims[2]; + + space_hid = H5Screate_simple (0, hdims, (hsize_t*) 0); + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.rows (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.cols (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m.nnz (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.cols() + 1; + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + int * itmp = m.xcidx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + + hdims[0] = m.nnz(); + hdims[1] = 1; + + space_hid = H5Screate_simple (2, hdims, 0); + + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + + data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_INT, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + retval = H5Dwrite (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + hid_t save_type_hid = H5T_NATIVE_DOUBLE; + + if (save_as_floats) + { + if (m.too_large_for_float ()) + { + warning ("save: some values too large to save as floats --"); + warning ("save: saving as doubles instead"); + } + else + save_type_hid = H5T_NATIVE_FLOAT; + } +#if HAVE_HDF5_INT2FLOAT_CONVERSIONS + // hdf5 currently doesn't support float/integer conversions + else + { + double max_val, min_val; + + if (m.all_integers (max_val, min_val)) + save_type_hid + = save_type_to_hdf5 (get_save_type (max_val, min_val)); + } +#endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */ + + data_hid = H5Dcreate (group_hid, "data", save_type_hid, space_hid, + H5P_DEFAULT); + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + double * dtmp = m.xdata (); + retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void*) dtmp) >= 0; + H5Dclose (data_hid); + H5Sclose (space_hid); + H5Gclose (group_hid); + + return retval; +} + +bool +octave_sparse_matrix::load_hdf5 (hid_t loc_id, const char *name, + bool /* have_h5giterate_bug */) +{ + int nr, nc, nz; + hid_t group_hid, data_hid, space_hid; + hsize_t rank; + + dim_vector dv; + int empty = load_hdf5_empty (loc_id, name, dv); + if (empty > 0) + matrix.resize(dv); + if (empty) + return (empty > 0); + + group_hid = H5Gopen (loc_id, name); + if (group_hid < 0 ) return false; + + data_hid = H5Dopen (group_hid, "nr"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nr) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nc"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nc) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "nz"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &nz) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + SparseMatrix m (nr, nc, nz); + + data_hid = H5Dopen (group_hid, "cidx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); + OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nc + 1 || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + int *itmp = m.xcidx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "ridx"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + itmp = m.xridx (); + if (H5Dread (data_hid, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) itmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + + data_hid = H5Dopen (group_hid, "data"); + space_hid = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 2) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sget_simple_extent_dims (space_hid, hdims, maxdims); + + if (hdims[0] != nz || hdims[1] != 1) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + double *dtmp = m.xdata (); + if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) dtmp) < 0) + { + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + + matrix = m; + + return true; +} +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-re-sparse.h b/src/ov-re-sparse.h new file mode 100644 --- /dev/null +++ b/src/ov-re-sparse.h @@ -0,0 +1,148 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_matrix_h) +#define octave_sparse_matrix_h 1 + +#include + +#include +#include + +#include "mx-base.h" +#include "oct-alloc.h" +#include "so-array.h" +#include "str-vec.h" + +#include "error.h" +#include "oct-stream.h" +#include "ov-base.h" +#include "ov-typeinfo.h" + +#include "dSparse.h" +#include "SparseType.h" +#include "ov-base-sparse.h" +#include "ov-bool-sparse.h" +#include "ov-cx-sparse.h" + +class Octave_map; +class octave_value_list; + +class tree_walker; + +class +octave_sparse_matrix : public octave_base_sparse +{ +public: + + octave_sparse_matrix (void) + : octave_base_sparse () { } + + octave_sparse_matrix (const Matrix& m) + : octave_base_sparse (SparseMatrix (m)) { } + + octave_sparse_matrix (const NDArray& m) + : octave_base_sparse (SparseMatrix (m)) { } + + octave_sparse_matrix (const SparseMatrix& m) + : octave_base_sparse (m) { } + + octave_sparse_matrix (const SparseMatrix& m, const SparseType& t) + : octave_base_sparse (m, t) { } + + octave_sparse_matrix (const MSparse& m) + : octave_base_sparse (m) { } + + octave_sparse_matrix (const octave_sparse_matrix& m) + : octave_base_sparse (m) { } + + ~octave_sparse_matrix (void) { } + + octave_value *clone (void) const { return new octave_sparse_matrix (*this); } + octave_value *empty_clone (void) const { return new octave_sparse_matrix (); } + + octave_value *try_narrowing_conversion (void); + +#if 0 + idx_vector index_vector (void) const { return idx_vector (matrix); } +#endif + + bool is_real_matrix (void) const { return true; } + + bool is_real_type (void) const { return true; } + + bool valid_as_scalar_index (void) const; + + double double_value (bool = false) const; + + double scalar_value (bool frc_str_conv = false) const + { return double_value (frc_str_conv); } + + Matrix matrix_value (bool = false) const; + + Complex complex_value (bool = false) const; + + ComplexMatrix complex_matrix_value (bool = false) const; + + ComplexNDArray complex_array_value (bool = false) const; + + NDArray array_value (bool = false) const; + + SparseMatrix sparse_matrix_value (bool = false) const + { return matrix; } + + SparseComplexMatrix sparse_complex_matrix_value (bool = false) const + { return SparseComplexMatrix (matrix); } + + streamoff_array streamoff_array_value (void) const; + +#if 0 + int write (octave_stream& os, int block_size, + oct_data_conv::data_type output_type, int skip, + oct_mach_info::float_format flt_fmt) const + { return os.write (matrix, block_size, output_type, skip, flt_fmt); } +#endif + + bool save_binary (std::ostream& os, bool& save_as_floats); + + bool load_binary (std::istream& is, bool swap, + oct_mach_info::float_format fmt); + +#if defined (HAVE_HDF5) + bool save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats); + + bool load_hdf5 (hid_t loc_id, const char *name, bool have_h5giterate_bug); +#endif + +private: + + DECLARE_OCTAVE_ALLOCATOR + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-uint16.cc b/src/ov-uint16.cc --- a/src/ov-uint16.cc +++ b/src/ov-uint16.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-uint32.cc b/src/ov-uint32.cc --- a/src/ov-uint32.cc +++ b/src/ov-uint32.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-uint64.cc b/src/ov-uint64.cc --- a/src/ov-uint64.cc +++ b/src/ov-uint64.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov-uint8.cc b/src/ov-uint8.cc --- a/src/ov-uint8.cc +++ b/src/ov-uint8.cc @@ -27,7 +27,6 @@ #include #include -#include #include "lo-ieee.h" #include "lo-utils.h" diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -38,6 +38,9 @@ #include "ov-cell.h" #include "ov-scalar.h" #include "ov-re-mat.h" +#include "ov-bool-sparse.h" +#include "ov-cx-sparse.h" +#include "ov-re-sparse.h" #include "ov-int8.h" #include "ov-int16.h" #include "ov-int32.h" @@ -602,6 +605,27 @@ maybe_mutate (); } +octave_value::octave_value (const SparseMatrix& m, const SparseType &t) + : rep (new octave_sparse_matrix (m, t)) +{ + rep->count = 1; + maybe_mutate (); +} + +octave_value::octave_value (const SparseComplexMatrix& m, const SparseType &t) + : rep (new octave_sparse_complex_matrix (m, t)) +{ + rep->count = 1; + maybe_mutate (); +} + +octave_value::octave_value (const SparseBoolMatrix& bm, const SparseType &t) + : rep (new octave_sparse_bool_matrix (bm, t)) +{ + rep->count = 1; + maybe_mutate (); +} + octave_value::octave_value (const octave_int8& i) : rep (new octave_int8_scalar (i)) { @@ -1705,6 +1729,13 @@ { octave_value retval; + // Rapid return for concatenation with an empty object. Dimension + // checking handled elsewhere. + if (v1.all_zero_dims ()) + return v2; + if (v2.all_zero_dims ()) + return v1; + int t1 = v1.type_id (); int t2 = v2.type_id (); @@ -2165,6 +2196,9 @@ octave_uint16_matrix::register_type (); octave_uint32_matrix::register_type (); octave_uint64_matrix::register_type (); + octave_sparse_bool_matrix::register_type (); + octave_sparse_matrix::register_type (); + octave_sparse_complex_matrix::register_type (); octave_struct::register_type (); octave_file::register_type (); octave_list::register_type (); diff --git a/src/ov.h b/src/ov.h --- a/src/ov.h +++ b/src/ov.h @@ -39,6 +39,7 @@ #include "oct-alloc.h" #include "oct-time.h" #include "str-vec.h" +#include "SparseType.h" class Cell; class streamoff_array; @@ -214,6 +215,11 @@ octave_value (const charMatrix& chm, bool is_string = false); octave_value (const charNDArray& chnda, bool is_string = false); octave_value (const ArrayN& chnda, bool is_string = false); + octave_value (const SparseMatrix& m, const SparseType& t = SparseType ()); + octave_value (const SparseComplexMatrix& m, + const SparseType& t = SparseType ()); + octave_value (const SparseBoolMatrix& bm, + const SparseType& t = SparseType ()); octave_value (const octave_int8& i); octave_value (const octave_int16& i); octave_value (const octave_int32& i); @@ -356,9 +362,14 @@ int ndims (void) const; + bool all_zero_dims (void) const { return dims().all_zero (); } + virtual int numel (void) const { return rep->numel (); } + virtual int capacity (void) const + { return rep->capacity (); } + virtual size_t byte_size (void) const { return rep->byte_size (); } @@ -568,6 +579,15 @@ virtual charNDArray char_array_value (bool frc_str_conv = false) const { return rep->char_array_value (frc_str_conv); } + virtual SparseMatrix sparse_matrix_value (bool frc_str_conv = false) const + { return rep->sparse_matrix_value (frc_str_conv); } + + virtual SparseComplexMatrix sparse_complex_matrix_value (bool frc_str_conv = false) const + { return rep->sparse_complex_matrix_value (frc_str_conv); } + + virtual SparseBoolMatrix sparse_bool_matrix_value (bool frc_str_conv = false) const + { return rep->sparse_bool_matrix_value (frc_str_conv); } + virtual octave_int8 int8_scalar_value (void) const { return rep->int8_scalar_value (); } diff --git a/src/pt-arg-list.cc b/src/pt-arg-list.cc --- a/src/pt-arg-list.cc +++ b/src/pt-arg-list.cc @@ -125,10 +125,6 @@ { case -1: { - // We want numel = prod (size ()) here, so don't use - // index_object->numel () as that may be different (it is - // the number of nonzero elements for sparse arrays). - int numel = dv.numel (); if (numel < 0) diff --git a/src/pt-mat.cc b/src/pt-mat.cc --- a/src/pt-mat.cc +++ b/src/pt-mat.cc @@ -592,10 +592,24 @@ ctmp = octave_value (charNDArray (dv, Vstring_fill_char), true); else { - if (all_empty_p) - ctmp = (*(tmp.begin() -> begin())); - else - ctmp = (*(tmp.begin() -> begin())).resize (dim_vector (0,0)).resize (dv); + // Find the first non-empty object + for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) + { + tm_row_const row = *p; + for (tm_row_const::iterator q = row.begin (); + q != row.end (); q++) + { + ctmp = *q; + if (! ctmp.all_zero_dims ()) + goto found_non_empty; + } + } + + ctmp = (*(tmp.begin() -> begin())); + + found_non_empty: + if (! all_empty_p) + ctmp = ctmp.resize (dim_vector (0,0)).resize (dv); } if (error_state) diff --git a/src/sparse-xdiv.cc b/src/sparse-xdiv.cc new file mode 100644 --- /dev/null +++ b/src/sparse-xdiv.cc @@ -0,0 +1,640 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "Array-util.h" +#include "oct-cmplx.h" +#include "quit.h" +#include "error.h" + +#include "dSparse.h" +#include "CSparse.h" +#include "oct-spparms.h" +#include "sparse-xdiv.h" + +static inline bool +result_ok (int info) +{ +#ifdef HAVE_LSSOLVE + return (info != -2 && info != -1); +#else + // If the matrix is singular, who cares as we don't have QR based solver yet + return (info != -1); +#endif +} + +static void +solve_singularity_warning (double rcond) +{ + warning ("matrix singular to machine precision, rcond = %g", rcond); + warning ("attempting to find minimum norm solution"); +} + +template +bool +mx_leftdiv_conform (const T1& a, const T2& b) +{ + int a_nr = a.rows (); + int b_nr = b.rows (); + + if (a_nr != b_nr) + { + int a_nc = a.cols (); + int b_nc = b.cols (); + + gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc); + return false; + } + + return true; +} + +#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \ + template bool mx_leftdiv_conform (const T1&, const T2&) + +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix); +INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix); + +template +bool +mx_div_conform (const T1& a, const T2& b) +{ + int a_nc = a.cols (); + int b_nc = b.cols (); + + if (a_nc != b_nc) + { + int a_nr = a.rows (); + int b_nr = b.rows (); + + gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc); + return false; + } + + return true; +} + +#define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \ + template bool mx_div_conform (const T1&, const T2&) + +INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix); +INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix); +INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix); +INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix); +INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix); +INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix); +INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix); +INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix); + +// Right division functions. +// +// op2 / op1: m cm sm scm +// +-- +---+----+----+----+ +// sparse matrix | 1 | 3 | 5 | 7 | +// +---+----+----+----+ +// sparse complex_matrix | 2 | 4 | 6 | 8 | +// +---+----+----+----+ + +// -*- 1 -*- +Matrix +xdiv (const Matrix& a, const SparseMatrix& b) +{ + if (! mx_div_conform (a, b)) + return Matrix (); + + Matrix atmp = a.transpose (); + SparseMatrix btmp = b.transpose (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + Matrix result = btmp.solve (atmp, info, rcond, + solve_singularity_warning); + + if (result_ok (info)) + return Matrix (result.transpose ()); + } + + int rank; + Matrix result = btmp.lssolve (atmp, info, rank); + + return result.transpose (); +} + +// -*- 2 -*- +ComplexMatrix +xdiv (const Matrix& a, const SparseComplexMatrix& b) +{ + if (! mx_div_conform (a, b)) + return ComplexMatrix (); + + Matrix atmp = a.transpose (); + SparseComplexMatrix btmp = b.hermitian (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + ComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// -*- 3 -*- +ComplexMatrix +xdiv (const ComplexMatrix& a, const SparseMatrix& b) +{ + if (! mx_div_conform (a, b)) + return ComplexMatrix (); + + ComplexMatrix atmp = a.hermitian (); + SparseMatrix btmp = b.transpose (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + ComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// -*- 4 -*- +ComplexMatrix +xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b) +{ + if (! mx_div_conform (a, b)) + return ComplexMatrix (); + + ComplexMatrix atmp = a.hermitian (); + SparseComplexMatrix btmp = b.hermitian (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + ComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// -*- 5 -*- +SparseMatrix +xdiv (const SparseMatrix& a, const SparseMatrix& b) +{ + if (! mx_div_conform (a, b)) + return SparseMatrix (); + + SparseMatrix atmp = a.transpose (); + SparseMatrix btmp = b.transpose (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + SparseMatrix result = btmp.solve (atmp, info, rcond, + solve_singularity_warning); + + if (result_ok (info)) + return SparseMatrix (result.transpose ()); + } + + int rank; + SparseMatrix result = btmp.lssolve (atmp, info, rank); + + return result.transpose (); +} + +// -*- 6 -*- +SparseComplexMatrix +xdiv (const SparseMatrix& a, const SparseComplexMatrix& b) +{ + if (! mx_div_conform (a, b)) + return SparseComplexMatrix (); + + SparseMatrix atmp = a.transpose (); + SparseComplexMatrix btmp = b.hermitian (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// -*- 7 -*- +SparseComplexMatrix +xdiv (const SparseComplexMatrix& a, const SparseMatrix& b) +{ + if (! mx_div_conform (a, b)) + return SparseComplexMatrix (); + + SparseComplexMatrix atmp = a.hermitian (); + SparseMatrix btmp = b.transpose (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// -*- 8 -*- +SparseComplexMatrix +xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b) +{ + if (! mx_div_conform (a, b)) + return SparseComplexMatrix (); + + SparseComplexMatrix atmp = a.hermitian (); + SparseComplexMatrix btmp = b.hermitian (); + + int info; + if (btmp.rows () == btmp.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = btmp.solve (atmp, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result.hermitian (); + } + + int rank; + SparseComplexMatrix result = btmp.lssolve (atmp, info, rank); + + return result.hermitian (); +} + +// Funny element by element division operations. +// +// op2 \ op1: s cs +// +-- +---+----+ +// matrix | 1 | 3 | +// +---+----+ +// complex_matrix | 2 | 4 | +// +---+----+ + +Matrix +x_el_div (double a, const SparseMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + Matrix result; + if (a == 0.) + result = Matrix (nr, nc, octave_NaN); + else if (a > 0.) + result = Matrix (nr, nc, octave_Inf); + else + result = Matrix (nr, nc, -octave_Inf); + + + for (int j = 0; j < nc; j++) + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + OCTAVE_QUIT; + result.elem (b.ridx(i), j) = a / b.data (i); + } + + return result; +} + +ComplexMatrix +x_el_div (double a, const SparseComplexMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + ComplexMatrix result (nr, nc, Complex(octave_NaN, octave_NaN)); + + for (int j = 0; j < nc; j++) + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + OCTAVE_QUIT; + result.elem (b.ridx(i), j) = a / b.data (i); + } + + return result; +} + +ComplexMatrix +x_el_div (const Complex a, const SparseMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + ComplexMatrix result (nr, nc, (a / 0.0)); + + for (int j = 0; j < nc; j++) + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + OCTAVE_QUIT; + result.elem (b.ridx(i), j) = a / b.data (i); + } + + return result; +} + +ComplexMatrix +x_el_div (const Complex a, const SparseComplexMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + ComplexMatrix result (nr, nc, (a / 0.0)); + + for (int j = 0; j < nc; j++) + for (int i = b.cidx(j); i < b.cidx(j+1); i++) + { + OCTAVE_QUIT; + result.elem (b.ridx(i), j) = a / b.data (i); + } + + return result; +} + +// Left division functions. +// +// op2 \ op1: m cm +// +-- +---+----+ +// matrix | 1 | 5 | +// +---+----+ +// complex_matrix | 2 | 6 | +// +---+----+ +// sparse matrix | 3 | 7 | +// +---+----+ +// sparse complex_matrix | 4 | 8 | +// +---+----+ + +// -*- 1 -*- +Matrix +xleftdiv (const SparseMatrix& a, const Matrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return Matrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + Matrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 2 -*- +ComplexMatrix +xleftdiv (const SparseMatrix& a, const ComplexMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return ComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 3 -*- +SparseMatrix +xleftdiv (const SparseMatrix& a, const SparseMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return SparseMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + SparseMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 4 -*- +SparseComplexMatrix +xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return SparseComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 5 -*- +ComplexMatrix +xleftdiv (const SparseComplexMatrix& a, const Matrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return ComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 6 -*- +ComplexMatrix +xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return ComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + ComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 7 -*- +SparseComplexMatrix +xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return SparseComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +// -*- 8 -*- +SparseComplexMatrix +xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b) +{ + if (! mx_leftdiv_conform (a, b)) + return SparseComplexMatrix (); + + int info; + if (a.rows () == a.columns ()) + { + double rcond = 0.0; + + SparseComplexMatrix result + = a.solve (b, info, rcond, solve_singularity_warning); + + if (result_ok (info)) + return result; + } + + int rank; + return a.lssolve (b, info, rank); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/sparse-xdiv.h b/src/sparse-xdiv.h new file mode 100644 --- /dev/null +++ b/src/sparse-xdiv.h @@ -0,0 +1,70 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_xdiv_h) +#define octave_sparse_xdiv_h 1 + +#include "oct-cmplx.h" + +class SparseMatrix; +class SparseComplexMatrix; + +extern Matrix xdiv (const Matrix& a, const SparseMatrix& b); +extern ComplexMatrix xdiv (const Matrix& a, const SparseComplexMatrix& b); +extern ComplexMatrix xdiv (const ComplexMatrix& a, const SparseMatrix& b); +extern ComplexMatrix xdiv (const ComplexMatrix& a, + const SparseComplexMatrix& b); + +extern SparseMatrix xdiv (const SparseMatrix& a, const SparseMatrix& b); +extern SparseComplexMatrix xdiv (const SparseMatrix& a, + const SparseComplexMatrix& b); +extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a, + const SparseMatrix& b); +extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a, + const SparseComplexMatrix& b); + +extern Matrix x_el_div (double a, const SparseMatrix& b); +extern ComplexMatrix x_el_div (double a, const SparseComplexMatrix& b); +extern ComplexMatrix x_el_div (const Complex a, const SparseMatrix& b); +extern ComplexMatrix x_el_div (const Complex a, + const SparseComplexMatrix& b); + +extern Matrix xleftdiv (const SparseMatrix& a, const Matrix& b); +extern ComplexMatrix xleftdiv (const SparseMatrix& a, const ComplexMatrix& b); +extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a, const Matrix& b); +extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a, + const ComplexMatrix& b); + +extern SparseMatrix xleftdiv (const SparseMatrix& a, const SparseMatrix& b); +extern SparseComplexMatrix xleftdiv (const SparseMatrix& a, + const SparseComplexMatrix& b); +extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a, + const SparseMatrix& b); +extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a, + const SparseComplexMatrix& b); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/sparse-xpow.cc b/src/sparse-xpow.cc new file mode 100644 --- /dev/null +++ b/src/sparse-xpow.cc @@ -0,0 +1,795 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "Array-util.h" +#include "oct-cmplx.h" +#include "quit.h" + +#include "error.h" +#include "oct-obj.h" +#include "utils.h" + +#include "dSparse.h" +#include "CSparse.h" +#include "ov-re-sparse.h" +#include "ov-cx-sparse.h" +#include "sparse-xpow.h" + +static inline int +xisint (double x) +{ + return (D_NINT (x) == x + && ((x >= 0 && x < INT_MAX) + || (x <= 0 && x > INT_MIN))); +} + + +// Safer pow functions. Only two make sense for sparse matrices, the +// others should all promote to full matrices. + +octave_value +xpow (const SparseMatrix& a, double b) +{ + octave_value retval; + + int nr = a.rows (); + int nc = a.cols (); + + if (nr == 0 || nc == 0 || nr != nc) + error ("for A^b, A must be square"); + else + { + if (static_cast (b) == b) + { + int btmp = static_cast (b); + if (btmp == 0) + { + SparseMatrix tmp = SparseMatrix (nr, nr, nr); + for (int i = 0; i < nr; i++) + { + tmp.data (i) = 1.0; + tmp.ridx (i) = i; + } + for (int i = 0; i < nr + 1; i++) + tmp.cidx (i) = i; + + retval = tmp; + } + else + { + SparseMatrix atmp; + if (btmp < 0) + { + btmp = -btmp; + + int info; + double rcond = 0.0; + + atmp = a.inverse (info, rcond, 1); + + if (info == -1) + warning ("inverse: matrix singular to machine\ + precision, rcond = %g", rcond); + } + else + atmp = a; + + SparseMatrix result (atmp); + + btmp--; + + while (btmp > 0) + { + if (btmp & 1) + result = result * atmp; + + btmp >>= 1; + + if (btmp > 0) + atmp = atmp * atmp; + } + + retval = result; + } + } + else + error ("use full(a) ^ full(b)"); + } + + return retval; +} + +octave_value +xpow (const SparseComplexMatrix& a, double b) +{ + octave_value retval; + + int nr = a.rows (); + int nc = a.cols (); + + if (nr == 0 || nc == 0 || nr != nc) + error ("for A^b, A must be square"); + else + { + if (static_cast (b) == b) + { + int btmp = static_cast (b); + if (btmp == 0) + { + SparseMatrix tmp = SparseMatrix (nr, nr, nr); + for (int i = 0; i < nr; i++) + { + tmp.data (i) = 1.0; + tmp.ridx (i) = i; + } + for (int i = 0; i < nr + 1; i++) + tmp.cidx (i) = i; + + retval = tmp; + } + else + { + SparseComplexMatrix atmp; + if (btmp < 0) + { + btmp = -btmp; + + int info; + double rcond = 0.0; + + atmp = a.inverse (info, rcond, 1); + + if (info == -1) + warning ("inverse: matrix singular to machine\ + precision, rcond = %g", rcond); + } + else + atmp = a; + + SparseComplexMatrix result (atmp); + + btmp--; + + while (btmp > 0) + { + if (btmp & 1) + result = result * atmp; + + btmp >>= 1; + + if (btmp > 0) + atmp = atmp * atmp; + } + + retval = result; + } + } + else + error ("use full(a) ^ full(b)"); + } + + return retval; +} + +// Safer pow functions that work elementwise for matrices. +// +// op2 \ op1: s m cs cm +// +-- +---+---+----+----+ +// scalar | | * | 3 | * | 9 | +// +---+---+----+----+ +// matrix | 1 | 4 | 7 | 10 | +// +---+---+----+----+ +// complex_scalar | * | 5 | * | 11 | +// +---+---+----+----+ +// complex_matrix | 2 | 6 | 8 | 12 | +// +---+---+----+----+ +// +// * -> not needed. + +// XXX FIXME XXX -- these functions need to be fixed so that things +// like +// +// a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b +// +// and +// +// a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end +// +// produce identical results. Also, it would be nice if -1^0.5 +// produced a pure imaginary result instead of a complex number with a +// small real part. But perhaps that's really a problem with the math +// library... + +// -*- 1 -*- +octave_value +elem_xpow (double a, const SparseMatrix& b) +{ + octave_value retval; + + int nr = b.rows (); + int nc = b.cols (); + + double d1, d2; + + if (a < 0.0 && ! b.all_integers (d1, d2)) + { + Complex atmp (a); + ComplexMatrix result (nr, nc); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + result (i, j) = pow (atmp, b(i,j)); + } + } + + retval = result; + } + else + { + Matrix result (nr, nc); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + result (i, j) = pow (a, b(i,j)); + } + } + + retval = result; + } + + return retval; +} + +// -*- 2 -*- +octave_value +elem_xpow (double a, const SparseComplexMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + Complex atmp (a); + ComplexMatrix result (nr, nc); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + result (i, j) = pow (atmp, b(i,j)); + } + } + + return result; +} + +// -*- 3 -*- +octave_value +elem_xpow (const SparseMatrix& a, double b) +{ + // XXX FIXME XXX What should a .^ 0 give?? Matlab gives a + // sparse matrix with same structure as a, which is strictly + // incorrect. Keep compatiability. + + octave_value retval; + + int nz = a.nnz (); + + if (b <= 0.0) + { + int nr = a.rows (); + int nc = a.cols (); + + if (static_cast (b) != b && a.any_element_is_negative ()) + { + ComplexMatrix result (nr, nc, Complex (pow (0.0, b))); + + // XXX FIXME XXX -- avoid apparent GNU libm bug by + // converting A and B to complex instead of just A. + Complex btmp (b); + + for (int j = 0; j < nc; j++) + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + OCTAVE_QUIT; + + Complex atmp (a.data (i)); + + result (a.ridx(i), j) = pow (atmp, btmp); + } + + retval = octave_value (result); + } + else + { + Matrix result (nr, nc, (pow (0.0, b))); + + for (int j = 0; j < nc; j++) + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + OCTAVE_QUIT; + result (a.ridx(i), j) = pow (a.data (i), b); + } + + retval = octave_value (result); + } + } + else if (static_cast (b) != b && a.any_element_is_negative ()) + { + SparseComplexMatrix result (a); + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + + // XXX FIXME XXX -- avoid apparent GNU libm bug by + // converting A and B to complex instead of just A. + + Complex atmp (a.data (i)); + Complex btmp (b); + + result.data (i) = pow (atmp, btmp); + } + + result.maybe_compress (true); + + retval = result; + } + else + { + SparseMatrix result (a); + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + result.data (i) = pow (a.data (i), b); + } + + result.maybe_compress (true); + + retval = result; + } + + return retval; +} + +// -*- 4 -*- +octave_value +elem_xpow (const SparseMatrix& a, const SparseMatrix& b) +{ + octave_value retval; + + int nr = a.rows (); + int nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (nr != b_nr || nc != b_nc) + { + gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); + return octave_value (); + } + + int convert_to_complex = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + double atmp = a (i, j); + double btmp = b (i, j); + if (atmp < 0.0 && static_cast (btmp) != btmp) + { + convert_to_complex = 1; + goto done; + } + } + +done: + + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) + nel++; + + if (convert_to_complex) + { + SparseComplexMatrix complex_result (nr, nc, nel); + + int ii = 0; + complex_result.cidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + Complex atmp (a (i, j)); + Complex btmp (b (i, j)); + Complex tmp = pow (atmp, btmp); + if (tmp != 0.) + { + complex_result.data (ii) = tmp; + complex_result.ridx (ii++) = i; + } + } + complex_result.cidx (j+1) = ii; + } + complex_result.maybe_compress (); + + retval = complex_result; + } + else + { + SparseMatrix result (nr, nc, nel); + int ii = 0; + + result.cidx (0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + double tmp = pow (a (i, j), b (i, j)); + if (tmp != 0.) + { + result.data (ii) = tmp; + result.ridx (ii++) = i; + } + } + result.cidx (j+1) = ii; + } + + result.maybe_compress (); + + retval = result; + } + + return retval; +} + +// -*- 5 -*- +octave_value +elem_xpow (const SparseMatrix& a, const Complex& b) +{ + octave_value retval; + + if (b == 0.0) + // Can this case ever happen, due to automatic retyping with maybe_mutate? + retval = octave_value (NDArray (a.dims (), 1)); + else + { + int nz = a.nnz (); + SparseComplexMatrix result (a); + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + result.data (i) = pow (Complex (a.data (i)), b); + } + + result.maybe_compress (true); + + retval = result; + } + + return retval; +} + +// -*- 6 -*- +octave_value +elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b) +{ + int nr = a.rows (); + int nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (nr != b_nr || nc != b_nc) + { + gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); + return octave_value (); + } + + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) + nel++; + + SparseComplexMatrix result (nr, nc, nel); + int ii = 0; + + result.cidx(0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + Complex tmp = pow (Complex (a (i, j)), b (i, j)); + if (tmp != 0.) + { + result.data (ii) = tmp; + result.ridx (ii++) = i; + } + } + result.cidx (j+1) = ii; + } + + result.maybe_compress (); + + return result; +} + +// -*- 7 -*- +octave_value +elem_xpow (const Complex& a, const SparseMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + ComplexMatrix result (nr, nc); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + double btmp = b (i, j); + if (xisint (btmp)) + result (i, j) = pow (a, static_cast (btmp)); + else + result (i, j) = pow (a, btmp); + } + } + + return result; +} + +// -*- 8 -*- +octave_value +elem_xpow (const Complex& a, const SparseComplexMatrix& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + ComplexMatrix result (nr, nc); + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + result (i, j) = pow (a, b (i, j)); + } + + return result; +} + +// -*- 9 -*- +octave_value +elem_xpow (const SparseComplexMatrix& a, double b) +{ + octave_value retval; + + if (b <= 0) + { + int nr = a.rows (); + int nc = a.cols (); + + ComplexMatrix result (nr, nc, Complex (pow (0.0, b))); + + if (xisint (b)) + { + for (int j = 0; j < nc; j++) + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + OCTAVE_QUIT; + result (a.ridx(i), j) = + pow (a.data (i), static_cast (b)); + } + } + else + { + for (int j = 0; j < nc; j++) + for (int i = a.cidx(j); i < a.cidx(j+1); i++) + { + OCTAVE_QUIT; + result (a.ridx(i), j) = pow (a.data (i), b); + } + } + + retval = result; + } + else + { + int nz = a.nnz (); + + SparseComplexMatrix result (a); + + if (xisint (b)) + { + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + result.data (i) = pow (a.data (i), static_cast (b)); + } + } + else + { + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + result.data (i) = pow (a.data (i), b); + } + } + + result.maybe_compress (true); + + retval = result; + } + + return retval; +} + +// -*- 10 -*- +octave_value +elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b) +{ + int nr = a.rows (); + int nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (nr != b_nr || nc != b_nc) + { + gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); + return octave_value (); + } + + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) + nel++; + + SparseComplexMatrix result (nr, nc, nel); + int ii = 0; + + result.cidx (0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + double btmp = b (i, j); + Complex tmp; + + if (xisint (btmp)) + tmp = pow (a (i, j), static_cast (btmp)); + else + tmp = pow (a (i, j), btmp); + if (tmp != 0.) + { + result.data (ii) = tmp; + result.ridx (ii++) = i; + } + } + result.cidx (j+1) = ii; + } + + result.maybe_compress (); + + return result; +} + +// -*- 11 -*- +octave_value +elem_xpow (const SparseComplexMatrix& a, const Complex& b) +{ + octave_value retval; + + if (b == 0.0) + // Can this case ever happen, due to automatic retyping with maybe_mutate? + retval = octave_value (NDArray (a.dims (), 1)); + else + { + + int nz = a.nnz (); + + SparseComplexMatrix result (a); + + for (int i = 0; i < nz; i++) + { + OCTAVE_QUIT; + result.data (i) = pow (a.data (i), b); + } + + result.maybe_compress (true); + + retval = result; + } + + return retval; +} + +// -*- 12 -*- +octave_value +elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b) +{ + int nr = a.rows (); + int nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (nr != b_nr || nc != b_nc) + { + gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc); + return octave_value (); + } + + int nel = 0; + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + if (!(a.elem (i, j) == 0. && b.elem (i, j) != 0.)) + nel++; + + SparseComplexMatrix result (nr, nc, nel); + int ii = 0; + + result.cidx (0) = 0; + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + Complex tmp = pow (a (i, j), b (i, j)); + if (tmp != 0.) + { + result.data (ii) = tmp; + result.ridx (ii++) = i; + } + } + result.cidx (j+1) = ii; + } + result.maybe_compress (true); + + return result; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/sparse-xpow.h b/src/sparse-xpow.h new file mode 100644 --- /dev/null +++ b/src/sparse-xpow.h @@ -0,0 +1,61 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#if !defined (octave_sparse_xpow_h) +#define octave_sparse_xpow_h 1 + +#include "oct-cmplx.h" + +class SparseMatrix; +class SparseComplexMatrix; +class octave_value; + +extern octave_value xpow (const SparseMatrix& a, double b); +extern octave_value xpow (const SparseComplexMatrix& a, double b); + +extern octave_value elem_xpow (double a, const SparseMatrix& b); +extern octave_value elem_xpow (double a, const SparseComplexMatrix& b); + +extern octave_value elem_xpow (const SparseMatrix& a, double b); +extern octave_value elem_xpow (const SparseMatrix& a, const SparseMatrix& b); +extern octave_value elem_xpow (const SparseMatrix& a, const Complex& b); +extern octave_value elem_xpow (const SparseMatrix& a, + const SparseComplexMatrix& b); + +extern octave_value elem_xpow (const Complex& a, const SparseMatrix& b); +extern octave_value elem_xpow (const Complex& a, + const SparseComplexMatrix& b); + +extern octave_value elem_xpow (const SparseComplexMatrix& a, double b); +extern octave_value elem_xpow (const SparseComplexMatrix& a, + const SparseMatrix& b); +extern octave_value elem_xpow (const SparseComplexMatrix& a, + const Complex& b); +extern octave_value elem_xpow (const SparseComplexMatrix& a, + const SparseComplexMatrix& b); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/symtab.cc b/src/symtab.cc --- a/src/symtab.cc +++ b/src/symtab.cc @@ -607,7 +607,7 @@ break; case 'e': - os << numel (); + os << capacity (); break; case 'n': @@ -1345,7 +1345,7 @@ > static_cast (param_length(pos_t))) ? str.length () : param_length(pos_t)); - elements1 = symbols(i)->numel (); + elements1 = symbols(i)->capacity (); ss1 << elements1; str = ss1.str (); param_length(pos_e) = ((str.length () @@ -1561,7 +1561,7 @@ for (int j = 0; j < len; j++) { symbols(j)->print_symbol_info_line (os, params); - elements += symbols(j)->numel (); + elements += symbols(j)->capacity (); bytes += symbols(j)->byte_size (); } diff --git a/src/symtab.h b/src/symtab.h --- a/src/symtab.h +++ b/src/symtab.h @@ -176,6 +176,9 @@ int numel (void) const { return definition.numel (); }; + int capacity (void) const + { return definition.capacity (); }; + dim_vector dims (void) const { return definition.dims (); } @@ -380,6 +383,9 @@ int numel (void) const { return definition->numel (); }; + int capacity (void) const + { return definition->capacity (); }; + dim_vector dims (void) const { return definition->dims (); } int dimensions_string_req_first_space (int print_dims) const; diff --git a/src/token.h b/src/token.h --- a/src/token.h +++ b/src/token.h @@ -23,10 +23,6 @@ #if !defined (octave_token_h) #define octave_token_h 1 -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma interface -#endif - #include class symbol_record;